diff --git a/res/shaders/simple.frag b/res/shaders/simple.frag index 73ab172..4fd1877 100644 --- a/res/shaders/simple.frag +++ b/res/shaders/simple.frag @@ -13,6 +13,11 @@ uniform LightSource lights[3]; uniform vec3 cameraPosition; uniform vec3 ballPosition; +layout(binding = 0) uniform sampler2D normalSampler; +layout(binding = 1) uniform sampler2D diffuseSampler; + +uniform int normalMapped; + out vec4 fragColor; const vec3 baseColor = vec3(1.0); @@ -39,44 +44,49 @@ float dither(vec2 uv) { void main() { - vec3 N = normalize(normal); - vec3 V = normalize(cameraPosition - worldPosition); + if (!bool(normalMapped)) { + vec3 N = normalize(normal); + vec3 V = normalize(cameraPosition - worldPosition); - // start with ambience - vec3 result = ambientStrength * baseColor; + // start with ambience + vec3 result = ambientStrength * baseColor; - for (int i = 0; i < 1; i++) { - vec3 toLight = lights[i].position - worldPosition; - vec3 L = normalize(toLight); - float dist = length(toLight); + for (int i = 0; i < 1; i++) { + vec3 toLight = lights[i].position - worldPosition; + vec3 L = normalize(toLight); + float dist = length(toLight); - float attenuation = 1.0 / (la + lb * dist + lc * dist * dist); + float attenuation = 1.0 / (la + lb * dist + lc * dist * dist); - float diff = max(dot(N, L), 0.0); - vec3 diffuse = diff * lights[i].color; + float diff = max(dot(N, L), 0.0); + vec3 diffuse = diff * lights[i].color; - // blinn-phong half-vector - vec3 H = normalize(L + V); - float spec = pow(max(dot(N, H), 0.0), shininess); - vec3 specular = specularStrength * spec * lights[i].color; + // blinn-phong half-vector + vec3 H = normalize(L + V); + float spec = pow(max(dot(N, H), 0.0), shininess); + vec3 specular = specularStrength * spec * lights[i].color; - vec3 toBall = ballPosition - worldPosition; - float projDist = dot(toBall, L); // distance along light ray - float perpDist = length(toBall - projDist * L); // perpendicular distance to ray - bool inShadowCone = (projDist > 0.0) && (projDist < dist); + vec3 toBall = ballPosition - worldPosition; + float projDist = dot(toBall, L); // distance along light ray + float perpDist = length(toBall - projDist * L); // perpendicular distance to ray + bool inShadowCone = (projDist > 0.0) && (projDist < dist); - float shadow = 1.0; - // skip ball's own light (index 2) to avoid self-shadowing the whole scene - if (inShadowCone) { - if (perpDist <= hardRadius) { - shadow = 0.0; - } else if (perpDist < softRadius) { - shadow = (perpDist - hardRadius) / (softRadius - hardRadius); + float shadow = 1.0; + // skip ball's own light (index 2) to avoid self-shadowing the whole scene + if (inShadowCone) { + if (perpDist <= hardRadius) { + shadow = 0.0; + } else if (perpDist < softRadius) { + shadow = (perpDist - hardRadius) / (softRadius - hardRadius); + } } + + result += shadow * attenuation * (diffuse + specular) * baseColor; } - result += shadow * attenuation * (diffuse + specular) * baseColor; + fragColor = vec4(result + dither(textureCoordinates), 1.0); + } else { + fragColor = texture(textureSampler, textureCoordinates); + // fragColor = vec4(1, 0, 0, 1); } - - fragColor = vec4(result + dither(textureCoordinates), 1.0); } diff --git a/res/shaders/simple.vert b/res/shaders/simple.vert index 091c861..52ed7d9 100644 --- a/res/shaders/simple.vert +++ b/res/shaders/simple.vert @@ -16,6 +16,6 @@ void main() { worldSpaceVertices = vec3(modelMatrix * vec4(position, 1.0)); normal_out = normalize(normalMatrix * normal_in); - textureCoordinates_out = textureCoordinates_in; gl_Position = MVP * vec4(position, 1.0f); + textureCoordinates_out = textureCoordinates_in; } diff --git a/res/shaders/texture.frag b/res/shaders/texture.frag index a81c55e..95e70c7 100644 --- a/res/shaders/texture.frag +++ b/res/shaders/texture.frag @@ -2,7 +2,7 @@ in layout(location = 1) vec2 textureCoordinates; -layout(binding = 0) uniform sampler2D textureSampler; +layout(binding = 4) uniform sampler2D textureSampler; out vec4 fragColor; diff --git a/src/gamelogic.cpp b/src/gamelogic.cpp index c27b823..a83e524 100644 --- a/src/gamelogic.cpp +++ b/src/gamelogic.cpp @@ -1,6 +1,8 @@ +#include "glm/fwd.hpp" #include "utilities/window.hpp" #include #include +#include #include #include #include @@ -44,7 +46,7 @@ SceneNode* rootNode; SceneNode* boxNode; SceneNode* ballNode; SceneNode* padNode; -SceneNode* textureNode; +SceneNode* textNode; std::vector lightNodes; std::vector lights; @@ -102,9 +104,8 @@ unsigned int createTextureFromImage(PNGImage *img) { glGenTextures(1, &tid); glBindTexture(GL_TEXTURE_2D, tid); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img->pixels.data()); - glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); return tid; } @@ -160,17 +161,23 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) { textureShader = new Gloom::Shader(); textureShader->makeBasicShader("../res/shaders/texture.vert", "../res/shaders/texture.frag"); - textureNode = createSceneNode(); + textNode = createSceneNode(); - auto img = loadPNGFile("../res/textures/charmap.png"); - textureNode->textureID = createTextureFromImage(&img); - auto textureMesh = generateTextGeometryBuffer("foo", 39.0 / 29, windowWidth); - textureNode->vertexArrayObjectID = generateBuffer(textureMesh); - textureNode->VAOIndexCount = textureMesh.indices.size(); - textureNode->nodeType = FLAT_GEOMETRY; + auto charmap = loadPNGFile("../res/textures/charmap.png"); + textNode->textureID = createTextureFromImage(&charmap); + auto textMesh = generateTextGeometryBuffer("made with love", 39.0 / 29, windowWidth/8.0); + textNode->vertexArrayObjectID = generateBuffer(textMesh); + textNode->VAOIndexCount = textMesh.indices.size(); + textNode->nodeType = FLAT_GEOMETRY; - rootNode->children.push_back(textureNode); - textureNode->position = {0, 0, 0}; + rootNode->children.push_back(textNode); + textNode->position = glm::vec3(0); + + auto normalImg = loadPNGFile("../res/textures/Brick03_nrm.png"); + boxNode->normalMapID = createTextureFromImage(&normalImg); + auto diffuseImg = loadPNGFile("../res/textures/Brick03_col.png"); + boxNode->diffuseID = createTextureFromImage(&diffuseImg); + boxNode->nodeType = NORMAL_MAPPED_GEOMETRY; std::cout << "loaded textures" << std::endl; @@ -352,7 +359,6 @@ void renderNode(SceneNode* node) { glUniformMatrix4fv(3, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrix)); glUniformMatrix4fv(4, 1, GL_FALSE, glm::value_ptr(node->modelMatrix)); glUniformMatrix3fv(5, 1, GL_FALSE, glm::value_ptr(node->normalMatrix)); - glUniform3fv(shader->getUniformFromName("cameraPosition"), 1, glm::value_ptr(cameraPosition)); glUniform3fv(shader->getUniformFromName("ballPosition"), 1, glm::value_ptr(ballPosition)); @@ -363,6 +369,13 @@ void renderNode(SceneNode* node) { } if (node->nodeType == GEOMETRY && node->vertexArrayObjectID != -1) { + glUniform1i(shader->getUniformFromName("normalMapped"), GL_FALSE); + glBindVertexArray(node->vertexArrayObjectID); + glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr); + } else if (node->nodeType == NORMAL_MAPPED_GEOMETRY) { + glUniform1i(shader->getUniformFromName("normalMapped"), GL_TRUE); + glBindTextureUnit(0, node->normalMapID); + glBindTextureUnit(1, node->diffuseID); glBindVertexArray(node->vertexArrayObjectID); glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr); } @@ -373,11 +386,11 @@ void renderNode(SceneNode* node) { } void renderTexture(SceneNode *node) { - auto orthoMatrix = glm::ortho(0.0f, static_cast(windowWidth), 0.0f, static_cast(windowHeight)); - GLint orthoLoc = textureShader->getUniformFromName("orthoMatrix"); - glUniformMatrix4fv(orthoLoc, 1, GL_FALSE, glm::value_ptr(orthoMatrix)); if (node->nodeType == FLAT_GEOMETRY) { - glBindTextureUnit(0, node->textureID); + auto orthoMatrix = glm::ortho(0.0f, static_cast(windowWidth), 0.0f, static_cast(windowHeight)); + GLint orthoLoc = textureShader->getUniformFromName("orthoMatrix"); + glUniformMatrix4fv(orthoLoc, 1, GL_FALSE, glm::value_ptr(orthoMatrix)); + glBindTextureUnit(4, node->textureID); glBindVertexArray(node->vertexArrayObjectID); glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr); } diff --git a/src/sceneGraph.hpp b/src/sceneGraph.hpp index d70b97e..7d13018 100644 --- a/src/sceneGraph.hpp +++ b/src/sceneGraph.hpp @@ -71,6 +71,8 @@ struct SceneNode { // normal map texture id unsigned int normalMapID; + + unsigned int diffuseID; }; SceneNode* createSceneNode();