From 733a8c0237d31a217038ff6581f1504a01bc4ff0 Mon Sep 17 00:00:00 2001 From: Fredrik Robertsen Date: Fri, 13 Feb 2026 20:36:14 +0100 Subject: [PATCH] emacs magic befell me and we are now done --- res/shaders/simple.frag | 13 ++++++++++-- res/shaders/simple.vert | 8 ++++++++ src/gamelogic.cpp | 7 +++++++ src/utilities/glutils.cpp | 43 +++++++++++++++++++++++++++++++++++++++ src/utilities/glutils.h | 11 +++++++++- src/utilities/mesh.h | 6 ++++-- src/utilities/shapes.cpp | 16 +++++++++++++++ 7 files changed, 99 insertions(+), 5 deletions(-) diff --git a/res/shaders/simple.frag b/res/shaders/simple.frag index 68218c5..8ec72d5 100644 --- a/res/shaders/simple.frag +++ b/res/shaders/simple.frag @@ -3,13 +3,14 @@ in layout(location = 0) vec3 normal_in; in layout(location = 1) vec2 textureCoordinates; in layout(location = 2) vec3 worldPosition; +in layout(location = 3) mat3 TBN; struct LightSource { vec3 position; vec3 color; }; -uniform LightSource lights[3]; +uniform LightSource lights[1]; uniform vec3 cameraPosition; uniform vec3 ballPosition; @@ -48,13 +49,19 @@ void main() vec3 normal = bool(normalMapped) ? 2*vec3(texture(normalSampler, textureCoordinates))-1 : normal_in; vec3 N = normalize(normal); + if (bool(normalMapped)) + N = TBN * N; vec3 V = normalize(cameraPosition - worldPosition); - + if (bool(normalMapped)) + V = TBN * V; + // use textures for normal mapped geometry vec3 result = ambientStrength * (bool(normalMapped) ? vec3(texture(diffuseSampler, textureCoordinates)) : baseColor); for (int i = 0; i < 1; i++) { vec3 toLight = lights[i].position - worldPosition; + if (bool(normalMapped)) + toLight = TBN * toLight; vec3 L = normalize(toLight); float dist = length(toLight); @@ -87,4 +94,6 @@ void main() } fragColor = vec4(result + dither(textureCoordinates), 1.0); + // DEBUG: use to see if tbn is correct. it is. + //fragColor = vec4(TBN * (texture(normalSampler, textureCoordinates).xyz * 2 - 1), 1.0); } diff --git a/res/shaders/simple.vert b/res/shaders/simple.vert index 52ed7d9..12bd5d9 100644 --- a/res/shaders/simple.vert +++ b/res/shaders/simple.vert @@ -3,6 +3,8 @@ in layout(location = 0) vec3 position; in layout(location = 1) vec3 normal_in; in layout(location = 2) vec2 textureCoordinates_in; +in layout(location = 6) vec3 tangents; +in layout(location = 7) vec3 bitangents; uniform layout(location = 3) mat4 MVP; uniform layout(location = 4) mat4 modelMatrix; @@ -11,9 +13,15 @@ uniform layout(location = 5) mat3 normalMatrix; out layout(location = 0) vec3 normal_out; out layout(location = 1) vec2 textureCoordinates_out; out layout(location = 2) vec3 worldSpaceVertices; +out layout(location = 3) mat3 TBN; void main() { + TBN = (mat3( + mat3(modelMatrix) * normalize(tangents), + mat3(modelMatrix) * normalize(bitangents), + mat3(modelMatrix) * normalize(normal_in) + )); worldSpaceVertices = vec3(modelMatrix * vec4(position, 1.0)); normal_out = normalize(normalMatrix * normal_in); gl_Position = MVP * vec4(position, 1.0f); diff --git a/src/gamelogic.cpp b/src/gamelogic.cpp index a83e524..bab731b 100644 --- a/src/gamelogic.cpp +++ b/src/gamelogic.cpp @@ -16,6 +16,8 @@ #include #include +#include "glm/gtx/string_cast.hpp" + #include #include #include @@ -125,6 +127,10 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) { Mesh boxMesh = cube(boxDimensions, glm::vec2(90), true, true); // inverted for interior view Mesh ballMesh = generateSphere(1.0, 40, 40); + for (auto v : boxMesh.bitangents) { + std::cout << glm::to_string(v) << std::endl; + } + unsigned int padVAO = generateBuffer(padMesh); unsigned int boxVAO = generateBuffer(boxMesh); unsigned int ballVAO = generateBuffer(ballMesh); @@ -362,6 +368,7 @@ void renderNode(SceneNode* node) { glUniform3fv(shader->getUniformFromName("cameraPosition"), 1, glm::value_ptr(cameraPosition)); glUniform3fv(shader->getUniformFromName("ballPosition"), 1, glm::value_ptr(ballPosition)); + for (size_t i = 0; i < lights.size(); i++) { std::string base = "lights[" + std::to_string(i) + "]"; glUniform3fv(shader->getUniformFromName((base + ".position").c_str()), 1, glm::value_ptr(lights[i].position)); diff --git a/src/utilities/glutils.cpp b/src/utilities/glutils.cpp index 2c1b465..59fe034 100644 --- a/src/utilities/glutils.cpp +++ b/src/utilities/glutils.cpp @@ -14,6 +14,43 @@ unsigned int generateAttribute(int id, int elementsPerEntry, std::vector data return bufferID; } +void computeTangentBasis( + // inputs + std::vector &vertices, + std::vector &uvs, + std::vector &normals, + // outputs + std::vector &tangents, + std::vector &bitangents +){ + for ( int i=0; i 0) { generateAttribute(2, 2, mesh.textureCoordinates, false); } + if (mesh.tangents.size() > 0) { + generateAttribute(6, 3, mesh.tangents, false); + } + if (mesh.bitangents.size() > 0) { + generateAttribute(7, 3, mesh.bitangents, false); + } unsigned int indexBufferID; glGenBuffers(1, &indexBufferID); diff --git a/src/utilities/glutils.h b/src/utilities/glutils.h index 6dea0b4..f4d5ab4 100644 --- a/src/utilities/glutils.h +++ b/src/utilities/glutils.h @@ -2,4 +2,13 @@ #include "mesh.h" -unsigned int generateBuffer(Mesh &mesh); \ No newline at end of file +unsigned int generateBuffer(Mesh &mesh); +void computeTangentBasis( + // inputs + std::vector &vertices, + std::vector &uvs, + std::vector &normals, + // outputs + std::vector &tangents, + std::vector &bitangents +); diff --git a/src/utilities/mesh.h b/src/utilities/mesh.h index ad2eb57..079a72e 100644 --- a/src/utilities/mesh.h +++ b/src/utilities/mesh.h @@ -7,6 +7,8 @@ struct Mesh { std::vector vertices; std::vector normals; std::vector textureCoordinates; - + std::vector tangents; + std::vector bitangents; + std::vector indices; -}; \ No newline at end of file +}; diff --git a/src/utilities/shapes.cpp b/src/utilities/shapes.cpp index 774789a..99ba9ec 100644 --- a/src/utilities/shapes.cpp +++ b/src/utilities/shapes.cpp @@ -1,5 +1,9 @@ #include #include "shapes.h" +#include "glutils.h" + +#define GLM_ENABLE_EXPERIMENTAL +#include "glm/gtx/string_cast.hpp" #ifndef M_PI #define M_PI 3.14159265359f @@ -87,6 +91,17 @@ Mesh cube(glm::vec3 scale, glm::vec2 textureScale, bool tilingTextures, bool inv } } + std::vector tangents; + std::vector bitangents; + computeTangentBasis(m.vertices, m.textureCoordinates, m.normals, tangents, bitangents); + m.tangents = tangents; + // printf("%d\n", tangents.at(0).x); + printf("tangents:\n"); + for (auto v : m.tangents) { + std::cout << glm::to_string(v); + } + m.bitangents = bitangents; + return m; } @@ -203,5 +218,6 @@ Mesh generateSphere(float sphereRadius, int slices, int layers) { mesh.normals = normals; mesh.indices = indices; mesh.textureCoordinates = uvs; + return mesh; }