From 9378c685a8ffe4992dda4abb2490d50c1af15147 Mon Sep 17 00:00:00 2001 From: Peder Bergebakken Sundt Date: Thu, 14 Mar 2019 12:43:41 +0100 Subject: [PATCH] Do ex2 --- .gitignore | 2 + res/shaders/simple.frag | 62 ++++++++++++++++++++---- res/shaders/simple.vert | 25 ++++++++-- src/gamelogic.cpp | 73 +++++++++++++++++++++++++--- src/program.cpp | 4 ++ src/sceneGraph.cpp | 4 +- src/sceneGraph.hpp | 15 +++++- src/utilities/glfont.cpp | 20 ++++++-- src/utilities/glutils.cpp | 89 ++++++++++++++++++++++++++++++++++- src/utilities/glutils.h | 8 +++- src/utilities/imageLoader.cpp | 2 +- src/utilities/mesh.h | 2 +- 12 files changed, 276 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 7170c9a..984eeab 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ *.app build/ + +res/textures/*.png diff --git a/res/shaders/simple.frag b/res/shaders/simple.frag index eb212a0..a4fe4ce 100644 --- a/res/shaders/simple.frag +++ b/res/shaders/simple.frag @@ -2,6 +2,20 @@ in layout(location = 0) vec3 normal; in layout(location = 1) vec3 vertex; +in layout(location = 2) vec2 UV; +in layout(location = 3) mat3 TBN; +layout(binding = 0) uniform sampler2D diffuseTexture; +layout(binding = 1) uniform sampler2D normalTexture; + +uniform bool isIlluminated; +uniform bool isTextured; +uniform bool isNormalMapped; +uniform bool isInverted; + +uniform layout(location = 6) mat4 MVP; +uniform layout(location = 7) mat4 MV; +uniform layout(location = 8) mat4 MVnormal; + // point lights struct Light { @@ -11,6 +25,7 @@ struct Light { vec3 spot_target; // MV space coordinates }; +//named #define N_LIGHTS 3 uniform Light light[N_LIGHTS]; @@ -23,18 +38,24 @@ vec3 c_diffuse = vec3(0.75390625, 0.4296875, 0.4375); vec3 c_emissive = vec3(0.01171875, 0.0, 0.15234375); vec3 c_specular = vec3(0.9453125, 0.94921875, 0.84765625); -float spot_cuttof_angle = cos(4 / 180.0 * 3.1415926535); +float spot_cuttof_angle = cos(1.5 / 180.0 * 3.1415926535); -void main() -{ - vec3 nnormal = normalize(normal); +void main_(vec4 basecolor) { + vec3 nnormal; + if (isNormalMapped) { + vec3 tangential = texture(normalTexture, UV).rgb * 2.0 - 1.0; + nnormal = TBN * -normalize(tangential); + } else { + nnormal = normalize(normal); + } float diffuse_intensity = 0.0; float specular_intensity = 0.0; for (int i = 0; i<3; i++) { vec3 L = vec3(light[i].MV * vec4(light[i].position, 1.0f)) - vertex; - float attenuation = clamp(1000/(1 + 40*length(L) + 0.1*length(L)*length(L)), 0.0, 1.25); + float l = length(L); + float attenuation = clamp(2000/(1 + 1*l + 0.1*l*l), 0.0, 1.25); L = normalize(L); if (light[i].is_spot) { @@ -42,7 +63,7 @@ void main() if (dot(L2, L) < spot_cuttof_angle) { continue; } - attenuation *= 70; + attenuation *= 30; } float diffuse_i = dot(nnormal, L); @@ -61,7 +82,30 @@ void main() //float intensity = dot(normalize(normal), normalize(light_pos_2)); //color = vec4(0.5 * normal + 0.5, 1.0); - color = vec4(c_emissive - + c_diffuse*diffuse_intensity - + c_specular*specular_intensity, 1.0f); + color = basecolor * vec4(c_emissive + + c_diffuse*diffuse_intensity, 1.0f) + + vec4(c_specular*specular_intensity, 1.0f); +} + + + +void main() { + if(isIlluminated) { + if (isTextured) { + c_diffuse = vec3(0.9); + c_emissive = vec3(0.2); + main_(texture(diffuseTexture, UV)); + } else { + main_(vec4(1.0)); + + } + } else { + color = texture(diffuseTexture, UV); + + } + if (isInverted) { + color.r = 1 - color.r; + color.g = 1 - color.g; + color.b = 1 - color.b; + } } diff --git a/res/shaders/simple.vert b/res/shaders/simple.vert index d15a76a..c8a588a 100644 --- a/res/shaders/simple.vert +++ b/res/shaders/simple.vert @@ -2,18 +2,33 @@ in layout(location = 0) vec3 position; in layout(location = 1) vec3 normal_in; +in layout(location = 2) vec2 UV; +in layout(location = 3) vec3 tangent; +in layout(location = 4) vec3 bitangent; -uniform layout(location = 3) mat4 MVP; -uniform layout(location = 4) mat4 MV; -uniform layout(location = 5) mat4 MVnormal; +uniform layout(location = 6) mat4 MVP; +uniform layout(location = 7) mat4 MV; +uniform layout(location = 8) mat4 MVnormal; +//named +uniform bool isIlluminated; +uniform bool isTextured; +uniform bool isNormalMapped; out layout(location = 0) vec3 normal_out; out layout(location = 1) vec3 vertex_out; +out layout(location = 2) vec2 uv_out; +out layout(location = 3) mat3 TBN; -void main() -{ +void main() { + TBN = mat3( + normalize(vec3(MV * vec4(tangent, 0.0))), + normalize(vec3(MV * vec4(bitangent, 0.0))), + normalize(vec3(MV * vec4(normal_in, 0.0))) + ); + normal_out = normalize(vec3(MVnormal * vec4(normal_in, 1.0f))); vertex_out = vec3(MV*vec4(position, 1.0f)); + uv_out = UV; gl_Position = MVP * vec4(position, 1.0f); } diff --git a/src/gamelogic.cpp b/src/gamelogic.cpp index c7670a0..3d87ff2 100644 --- a/src/gamelogic.cpp +++ b/src/gamelogic.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -33,6 +35,8 @@ SceneNode* rootNode; SceneNode* boxNode; SceneNode* ballNode; SceneNode* padNode; +SceneNode* hudNode; +SceneNode* textNode; SceneNode* lightNode[3]; @@ -61,7 +65,11 @@ bool jumpedToNextFrame = false; const float debug_startTime = 45; double totalElapsedTime = debug_startTime; +// textures +PNGImage t_charmap; +PNGImage t_cobble_diff; +PNGImage t_cobble_normal; void mouseCallback(GLFWwindow* window, double x, double y) { int windowWidth, windowHeight; @@ -107,20 +115,37 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) { Mesh sphere = generateSphere(1.0, 40, 40); unsigned int ballVAO = generateBuffer(sphere); - unsigned int boxVAO = generateBuffer(box); + unsigned int boxVAO = generateBuffer(box, true); unsigned int padVAO = generateBuffer(pad); + // textures + t_charmap = loadPNGFile("../res/textures/charmap.png"); + t_cobble_diff = loadPNGFile("../res/textures/cobble_diff.png"); + t_cobble_normal = loadPNGFile("../res/textures/cobble_normal.png"); + + unsigned int t_charmapID = generateTexture(t_charmap); + unsigned int t_cobble_diffID = generateTexture(t_cobble_diff); + unsigned int t_cobble_normalID = generateTexture(t_cobble_normal); + rootNode = createSceneNode(); - boxNode = createSceneNode() ; + boxNode = createSceneNode(NORMAL_TEXTURED_GEOMETRY); padNode = createSceneNode(); ballNode = createSceneNode(); + hudNode = createSceneNode(HUD); + textNode = createSceneNode(TEXTURED_GEOMETRY); rootNode->children.push_back(boxNode); rootNode->children.push_back(padNode); rootNode->children.push_back(ballNode); + rootNode->children.push_back(hudNode); + + hudNode->children.push_back(textNode); + //rootNode->children.push_back(textNode); boxNode->vertexArrayObjectID = boxVAO; boxNode->VAOIndexCount = box.indices.size(); + boxNode->diffuseTextureID = t_cobble_diffID; + boxNode->normalTextureID = t_cobble_normalID; padNode->vertexArrayObjectID = padVAO; padNode->VAOIndexCount = pad.indices.size(); @@ -138,12 +163,24 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) { rootNode->children.push_back(lightNode[1]); ballNode->children.push_back(lightNode[2]); lightNode[0]->position = {boxDimensions.x/2 - 10, boxDimensions.y/2 - 10, boxDimensions.z/2 - 10}; - lightNode[1]->position = {300,300,400}; + lightNode[1]->position = {-300, -500, 300}; lightNode[2]->position = {0, 0, 0}; lightNode[1]->nodeType = SPOT_LIGHT; padNode->targeted_by = lightNode[1]; - + + + // hud + Mesh hello_world = generateTextGeometryBuffer("Skjer'a bagera?", 1.3, 2); + textNode->position = glm::vec3(-1.0, 0.0, 0.0); + textNode->rotation = glm::vec3(0.0, 0.0, 0.0); + textNode->vertexArrayObjectID = generateBuffer(hello_world); + textNode->VAOIndexCount = hello_world.indices.size(); + textNode->diffuseTextureID = t_charmapID; + textNode->isIlluminated = false; + textNode->isInverted = true; + + getTimeDeltaSeconds(); std::cout << "Ready. Click to start!" << std::endl; @@ -154,6 +191,14 @@ void updateNodeTransformations(SceneNode* node, glm::mat4 transformationThusFar, glm::mat4 transformationMatrix(1.0); switch(node->nodeType) { + case HUD: + // We orthographic now, bitches! + // set orthographic VP + V = glm::mat4(1.0); + P = glm::ortho(-float(windowWidth) / float(windowHeight), float(windowWidth) / float(windowHeight), -1.0f, 1.0f);//, -10.0f, 120.0f); + break; + case NORMAL_TEXTURED_GEOMETRY: + case TEXTURED_GEOMETRY: case GEOMETRY: transformationMatrix = glm::translate(glm::mat4(1.0), node->position) @@ -342,13 +387,25 @@ void updateFrame(GLFWwindow* window) { void renderNode(SceneNode* node) { - glUniformMatrix4fv(3, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrix)); - glUniformMatrix4fv(4, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrixMV)); - glUniformMatrix4fv(5, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrixMVnormal)); + glUniformMatrix4fv(6, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrix)); + glUniformMatrix4fv(7, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrixMV)); + glUniformMatrix4fv(8, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrixMVnormal)); + glUniform1ui(shader->location("isNormalMapped"), false); + glUniform1ui(shader->location("isTextured"), false); switch(node->nodeType) { + case NORMAL_TEXTURED_GEOMETRY: + glUniform1ui(shader->location("isNormalMapped"), true); + glBindTextureUnit(1, node->normalTextureID); + [[fallthrough]]; + case TEXTURED_GEOMETRY: + glUniform1ui(shader->location("isTextured"), true); + glBindTextureUnit(0, node->diffuseTextureID); + [[fallthrough]]; case GEOMETRY: if(node->vertexArrayObjectID != -1) { + glUniform1ui(shader->location("isIlluminated"), node->isIlluminated); + glUniform1ui(shader->location("isInverted"), node->isInverted); glBindVertexArray(node->vertexArrayObjectID); glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr); } @@ -365,6 +422,8 @@ void renderNode(SceneNode* node) { break; } + case HUD: + break; } for(SceneNode* child : node->children) { diff --git a/src/program.cpp b/src/program.cpp index 606d88f..c334481 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -24,6 +24,10 @@ void runProgram(GLFWwindow* window, CommandLineOptions options) // Configure miscellaneous OpenGL settings glEnable(GL_CULL_FACE); + //enable alpha + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // Set default colour after clearing the colour buffer glClearColor(0.3f, 0.5f, 0.8f, 1.0f); diff --git a/src/sceneGraph.cpp b/src/sceneGraph.cpp index 518d8e7..92408d7 100644 --- a/src/sceneGraph.cpp +++ b/src/sceneGraph.cpp @@ -4,6 +4,9 @@ SceneNode* createSceneNode() { return new SceneNode(); } +SceneNode* createSceneNode(SceneNodeType type) { + return new SceneNode(type); +} // Add a child node to its parent's list of children void addChild(SceneNode* parent, SceneNode* child) { @@ -26,4 +29,3 @@ void printNode(SceneNode* node) { node->referencePoint.x, node->referencePoint.y, node->referencePoint.z, node->vertexArrayObjectID); } - diff --git a/src/sceneGraph.hpp b/src/sceneGraph.hpp index d48df58..05d4b7b 100644 --- a/src/sceneGraph.hpp +++ b/src/sceneGraph.hpp @@ -14,7 +14,7 @@ #include enum SceneNodeType { - GEOMETRY, POINT_LIGHT, SPOT_LIGHT + GEOMETRY, POINT_LIGHT, SPOT_LIGHT, HUD, TEXTURED_GEOMETRY, NORMAL_TEXTURED_GEOMETRY }; // In case you haven't got much experience with C or C++, let me explain this "typedef" you see below. @@ -33,6 +33,12 @@ struct SceneNode { nodeType = GEOMETRY; targeted_by = nullptr; + + isIlluminated = true; + isInverted = false; + } + SceneNode(SceneNodeType type) : SceneNode() { + nodeType = type; } // A list of all children that belong to this node. @@ -55,6 +61,12 @@ struct SceneNode { // The ID of the VAO containing the "appearance" of this SceneNode. int vertexArrayObjectID; unsigned int VAOIndexCount; + + unsigned int diffuseTextureID; + unsigned int normalTextureID; + + bool isIlluminated; + bool isInverted; // Node type is used to determine how to handle the contents of a node SceneNodeType nodeType; @@ -67,6 +79,7 @@ struct SceneNode { // Struct for keeping track of 2D coordinates SceneNode* createSceneNode(); +SceneNode* createSceneNode(SceneNodeType type); void addChild(SceneNode* parent, SceneNode* child); void printNode(SceneNode* node); diff --git a/src/utilities/glfont.cpp b/src/utilities/glfont.cpp index 79397f0..b5917a0 100644 --- a/src/utilities/glfont.cpp +++ b/src/utilities/glfont.cpp @@ -4,7 +4,8 @@ Mesh generateTextGeometryBuffer(std::string text, float characterHeightOverWidth, float totalTextWidth) { float characterWidth = totalTextWidth / float(text.length()); float characterHeight = characterHeightOverWidth * characterWidth; - + float textureWidth = 1.0 / 128.0; + unsigned int vertexCount = 4 * text.length(); unsigned int indexCount = 6 * text.length(); @@ -12,11 +13,14 @@ Mesh generateTextGeometryBuffer(std::string text, float characterHeightOverWidth mesh.vertices.resize(vertexCount); mesh.indices.resize(indexCount); + mesh.textureCoordinates.resize(vertexCount); + for(unsigned int i = 0; i < text.length(); i++) { float baseXCoordinate = float(i) * characterWidth; - + float baseXTexture = float(text[i]) * textureWidth; + mesh.vertices.at(4 * i + 0) = {baseXCoordinate, 0, 0}; mesh.vertices.at(4 * i + 1) = {baseXCoordinate + characterWidth, 0, 0}; mesh.vertices.at(4 * i + 2) = {baseXCoordinate + characterWidth, characterHeight, 0}; @@ -32,7 +36,17 @@ Mesh generateTextGeometryBuffer(std::string text, float characterHeightOverWidth mesh.indices.at(6 * i + 3) = 4 * i + 0; mesh.indices.at(6 * i + 4) = 4 * i + 2; mesh.indices.at(6 * i + 5) = 4 * i + 3; + + + mesh.textureCoordinates.at(4 * i + 0) = {baseXTexture, 0}; + mesh.textureCoordinates.at(4 * i + 1) = {baseXTexture + textureWidth, 0}; + mesh.textureCoordinates.at(4 * i + 2) = {baseXTexture + textureWidth, 1}; + + mesh.textureCoordinates.at(4 * i + 0) = {baseXTexture, 0}; + mesh.textureCoordinates.at(4 * i + 2) = {baseXTexture + textureWidth, 1}; + mesh.textureCoordinates.at(4 * i + 3) = {baseXTexture, 1}; + } return mesh; -} \ No newline at end of file +} diff --git a/src/utilities/glutils.cpp b/src/utilities/glutils.cpp index 26752e1..02a394f 100644 --- a/src/utilities/glutils.cpp +++ b/src/utilities/glutils.cpp @@ -2,7 +2,7 @@ #include #include "glutils.h" -unsigned int generateBuffer(Mesh &mesh) { +unsigned int generateBuffer(Mesh &mesh, bool isNormalMapped) { unsigned int vaoID; glGenVertexArrays(1, &vaoID); glBindVertexArray(vaoID); @@ -26,6 +26,93 @@ unsigned int generateBuffer(Mesh &mesh) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.indices.size() * sizeof(unsigned int), mesh.indices.data(), GL_STATIC_DRAW); + if (mesh.textureCoordinates.empty()) return vaoID; + + unsigned int textureBufferID; + glGenBuffers(1, &textureBufferID); + glBindBuffer(GL_ARRAY_BUFFER, textureBufferID); + glBufferData(GL_ARRAY_BUFFER, mesh.textureCoordinates.size() * sizeof(glm::vec2), mesh.textureCoordinates.data(), GL_STATIC_DRAW); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0); + glEnableVertexAttribArray(2); + + if (isNormalMapped) addTangents(vaoID, mesh); return vaoID; } + +void addTangents(unsigned int vaoID, Mesh& mesh) { + glm::vec3 tangents[mesh.vertices.size()]; + glm::vec3 bitangents[mesh.vertices.size()]; + + for (unsigned int i = 0; i < mesh.indices.size(); i+=3) { + const glm::vec3& pos1 = mesh.vertices[mesh.indices[i+0]]; + const glm::vec3& pos2 = mesh.vertices[mesh.indices[i+1]]; + const glm::vec3& pos3 = mesh.vertices[mesh.indices[i+2]]; + + const glm::vec2& uv1 = mesh.textureCoordinates[mesh.indices[i+0]]; + const glm::vec2& uv2 = mesh.textureCoordinates[mesh.indices[i+1]]; + const glm::vec2& uv3 = mesh.textureCoordinates[mesh.indices[i+2]]; + + glm::vec3 edge1 = pos2 - pos1; + glm::vec3 edge2 = pos3 - pos1; + glm::vec2 deltaUV1 = uv2 - uv1; + glm::vec2 deltaUV2 = uv3 - uv1; + + float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y); + + glm::vec3 tangent, bitangent; + tangent.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x); + tangent.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y); + tangent.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z); + + bitangent.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x); + bitangent.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y); + bitangent.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z); + + tangent = glm::normalize(tangent); + bitangent = glm::normalize(bitangent); + + // handedness + tangents[i+0] = -tangent; + tangents[i+1] = -tangent; + tangents[i+2] = -tangent; + bitangents[i+0] = -bitangent; + bitangents[i+1] = -bitangent; + bitangents[i+2] = -bitangent; + } + + glBindVertexArray(vaoID); + + unsigned int tangentBufferID; + glGenBuffers(1, &tangentBufferID); + glBindBuffer(GL_ARRAY_BUFFER, tangentBufferID); + glBufferData(GL_ARRAY_BUFFER, mesh.vertices.size() * sizeof(glm::vec3), tangents, GL_STATIC_DRAW); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0); + glEnableVertexAttribArray(3); + + unsigned int bitangentBufferID; + glGenBuffers(1, &bitangentBufferID); + glBindBuffer(GL_ARRAY_BUFFER, bitangentBufferID); + glBufferData(GL_ARRAY_BUFFER, mesh.vertices.size() * sizeof(glm::vec3), bitangents, GL_STATIC_DRAW); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0); + glEnableVertexAttribArray(4); +} + +unsigned int generateTexture(PNGImage& texture) { + unsigned int id; + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_2D, id); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.pixels.data()); + //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.pixels.data()); + + glGenerateMipmap(GL_TEXTURE_2D); + + return id; +} diff --git a/src/utilities/glutils.h b/src/utilities/glutils.h index 6dea0b4..3ad25fb 100644 --- a/src/utilities/glutils.h +++ b/src/utilities/glutils.h @@ -1,5 +1,11 @@ #pragma once #include "mesh.h" +#include "imageLoader.hpp" -unsigned int generateBuffer(Mesh &mesh); \ No newline at end of file + +unsigned int generateBuffer(Mesh &mesh, bool isNormalMapped = false); + +void addTangents(unsigned int vaoID, Mesh& mesh); + +unsigned int generateTexture(PNGImage& texture); diff --git a/src/utilities/imageLoader.cpp b/src/utilities/imageLoader.cpp index 88a708a..ac09551 100644 --- a/src/utilities/imageLoader.cpp +++ b/src/utilities/imageLoader.cpp @@ -38,4 +38,4 @@ PNGImage loadPNGFile(std::string fileName) return image; -} \ No newline at end of file +} diff --git a/src/utilities/mesh.h b/src/utilities/mesh.h index ad2eb57..00837ee 100644 --- a/src/utilities/mesh.h +++ b/src/utilities/mesh.h @@ -9,4 +9,4 @@ struct Mesh { std::vector textureCoordinates; std::vector indices; -}; \ No newline at end of file +};