diff --git a/ECS/Components/Mesh.h b/ECS/Components/Mesh.h index 1f7b949..c5794aa 100644 --- a/ECS/Components/Mesh.h +++ b/ECS/Components/Mesh.h @@ -33,17 +33,25 @@ struct Mesh { glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // position attribute - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // Normal attribute - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); // texture coord attribute - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); + // Tangent attribute + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(8 * sizeof(float))); + glEnableVertexAttribArray(3); + + // Bitangent attribute + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), (void*)(11 * sizeof(float))); + glEnableVertexAttribArray(4); + glBindVertexArray(0); } diff --git a/ECS/Components/ObjMesh.h b/ECS/Components/ObjMesh.h index 7f5d3ac..2b26374 100644 --- a/ECS/Components/ObjMesh.h +++ b/ECS/Components/ObjMesh.h @@ -39,16 +39,27 @@ private: std::vector vertexData = std::vector(); - // Go through each vertex - for (auto &Vertice : curMesh.Vertices) { - vertexData.emplace_back(Vertice.Position.X); - vertexData.emplace_back(Vertice.Position.Y); - vertexData.emplace_back(Vertice.Position.Z); - vertexData.emplace_back(Vertice.Normal.X); - vertexData.emplace_back(Vertice.Normal.Y); - vertexData.emplace_back(Vertice.Normal.Z); - vertexData.emplace_back(Vertice.TextureCoordinate.X); - vertexData.emplace_back(Vertice.TextureCoordinate.Y); + auto tangents = getTangentsFromVertices(curMesh.Vertices, getIndicesFromFile(path)); + + for (int i = 0; i <= curMesh.Vertices.size(); i++) { + auto vertex = curMesh.Vertices[i]; + auto tangent = tangents.first[i]; + auto bitangent = tangents.second[i]; + + vertexData.emplace_back(vertex.Position.X); + vertexData.emplace_back(vertex.Position.Y); + vertexData.emplace_back(vertex.Position.Z); + vertexData.emplace_back(vertex.Normal.X); + vertexData.emplace_back(vertex.Normal.Y); + vertexData.emplace_back(vertex.Normal.Z); + vertexData.emplace_back(vertex.TextureCoordinate.X); + vertexData.emplace_back(vertex.TextureCoordinate.Y); + vertexData.emplace_back(tangent.x); + vertexData.emplace_back(tangent.y); + vertexData.emplace_back(tangent.z); + vertexData.emplace_back(bitangent.x); + vertexData.emplace_back(bitangent.y); + vertexData.emplace_back(bitangent.z); } return vertexData; @@ -58,6 +69,58 @@ private: } } + static std::pair, std::vector> getTangentsFromVertices(const std::vector &vertices, const std::vector indices) { + // These vectors hold tangents and bitangents in the same way in which the vertices vectors holds vertices: + // Their index in the vector corresponds to indices in the indices vector. + std::vector tangents(vertices.size()); + std::vector bitangents(vertices.size()); + + // Iterate over all triangles + for (uint index = 0; index < indices.size(); index += 3) { + // Index in vertex buffer + uint i0 = indices[index]; + uint i1 = indices[index + 1]; + uint i2 = indices[index + 2]; + + // Inputs + glm::vec3 vertex0 = glm::vec3(vertices[i0].Position.X, vertices[i0].Position.Y, vertices[i0].Position.Z); + glm::vec3 vertex1 = glm::vec3(vertices[i1].Position.X, vertices[i1].Position.Y, vertices[i1].Position.Z); + glm::vec3 vertex2 = glm::vec3(vertices[i2].Position.X, vertices[i2].Position.Y, vertices[i2].Position.Z); + + glm::vec2 uv0 = glm::vec2(vertices[i0].TextureCoordinate.X, vertices[i0].TextureCoordinate.Y); + glm::vec2 uv1 = glm::vec2(vertices[i1].TextureCoordinate.X, vertices[i1].TextureCoordinate.Y); + glm::vec2 uv2 = glm::vec2(vertices[i2].TextureCoordinate.X, vertices[i2].TextureCoordinate.Y); + + glm::vec3 normal0 = glm::vec3(vertices[i0].Normal.X, vertices[i0].Normal.Y, vertices[i0].Normal.Z); + glm::vec3 normal1 = glm::vec3(vertices[i1].Normal.X, vertices[i1].Normal.Y, vertices[i1].Normal.Z); + glm::vec3 normal2 = glm::vec3(vertices[i2].Normal.X, vertices[i2].Normal.Y, vertices[i2].Normal.Z); + + // Edges of the triangle : position delta + glm::vec3 deltaPos1 = vertex1 - vertex0; + glm::vec3 deltaPos2 = vertex2 - vertex0; + + // UV delta + glm::vec2 deltaUV1 = uv1 - uv0; + glm::vec2 deltaUV2 = uv2 - uv0; + + float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x); + glm::vec3 tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y)*r; + glm::vec3 bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x)*r; + + // Add the tangent and bitangent to the current value in the array. + // This is done to get an average in the end. + tangents[i0] += tangent; + tangents[i1] += tangent; + tangents[i2] += tangent; + + bitangents[i0] += bitangent; + bitangents[i1] += bitangent; + bitangents[i2] += bitangent; + } + + return std::pair, std::vector>(tangents, bitangents); + } + static std::vector getIndicesFromFile(const std::string &path) { objl::Loader loader; diff --git a/Shaders/default-vertex.vs b/Shaders/default-vertex.vs index 2f8d8ed..596e0b7 100644 --- a/Shaders/default-vertex.vs +++ b/Shaders/default-vertex.vs @@ -2,6 +2,8 @@ layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 NORMAL; layout (location = 2) in vec2 UV; +layout (location = 3) in vec3 TANGENT; +layout (location = 4) in vec3 BITANGENT; out vec2 TexCoord; out vec3 Normal;