diff --git a/engine b/engine index 3387d69..c944b78 160000 --- a/engine +++ b/engine @@ -1 +1 @@ -Subproject commit 3387d6971c46cedce93a6350a0b25afea5412914 +Subproject commit c944b7866878c9f5db238384b4b194d53cf6081c diff --git a/src/main.cpp b/src/main.cpp index 8218d91..8bc7daa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "shader.h" @@ -44,9 +45,11 @@ int main(int argc, char** argv) { } std::vector verticies; + std::vector normals; std::vector texture; - std::vector faceIndex; + std::vector faceIndex; std::vector textureIndex; + std::vector normalIndex; std::string line; while (std::getline(in, line)) { @@ -58,39 +61,107 @@ int main(int argc, char** argv) { verticies.push_back(glm::vec3(x, y, z)); } else if (prefix == "vt") { // texture coordinates std::istringstream l(line.substr(3)); - int u, v ; + double u, v ; l >> u; l >> v; texture.push_back(glm::vec2(u, v)); + } else if (prefix == "vn") { // texture coordinates + std::istringstream l(line.substr(3)); + double x,y,z; + l >> x; l >> y; l >> z; + normals.push_back(glm::vec3(x, y, z)); } else if (prefix == "f ") { // faces - const char* c = line.substr(2).c_str(); - int vA, vB, vC, tA, tB, tC; - sscanf(c, "%i/%i %i/%i %i/%i", &vA, &tA, &vB, &tB, &vC, &tC); + std::string l = line.substr(2); + const char* c = l.c_str(); + unsigned int vA, vB, vC, vD, tA, tB, tC, tD, nA, nB, nC, nD; + int count = sscanf(c, "%i/%i/%i %i/%i/%i %i/%i/%i %i/%i/%i", &vA, &tA, &nA, &vB, &tB, &nB, &vC, &tC, &nC, &vD, &tD, &nD); + faceIndex.push_back(vA -1); faceIndex.push_back(vB -1); faceIndex.push_back(vC -1); textureIndex.push_back(tA -1); textureIndex.push_back(tB -1); textureIndex.push_back(tC -1); + normalIndex.push_back(nA -1); + normalIndex.push_back(nB -1); + normalIndex.push_back(nC -1); + + if (count == 12) { + faceIndex.push_back(vA -1); + faceIndex.push_back(vC -1); + faceIndex.push_back(vD -1); + textureIndex.push_back(tA -1); + textureIndex.push_back(tC -1); + textureIndex.push_back(tD -1); + normalIndex.push_back(nA -1); + normalIndex.push_back(nC -1); + normalIndex.push_back(nD -1); + } } } - Engine::Buffer vbo(verticies.size()); - for (int i = 0; i < verticies.size(); ++i) { - vbo[i] = verticies[i]; - } - vbo.flush(); - + Engine::Buffer vbo(faceIndex.size()); + Engine::Buffer norm(faceIndex.size()); + Engine::Buffer uvs(faceIndex.size()); Engine::Buffer elements(faceIndex.size(), GL_ELEMENT_ARRAY_BUFFER); for (int i = 0; i < faceIndex.size(); ++i) { - elements[i] = faceIndex[i]; + elements[i] = i; + vbo[i] = verticies[faceIndex[i]]; + norm[i] = normals[normalIndex[i]]; + uvs[i] = texture[textureIndex[i]]; + } + + Engine::Buffer tangent(faceIndex.size()); + Engine::Buffer bitangent(faceIndex.size()); + for (int i = 0; i < faceIndex.size(); i+=3) { + glm::vec3 pos1 = verticies[faceIndex[i]]; + glm::vec3 pos2 = verticies[faceIndex[i+1]]; + glm::vec3 pos3 = verticies[faceIndex[i+2]]; + glm::vec2 uv1 = texture[textureIndex[i]]; + glm::vec2 uv2 = texture[textureIndex[i+1]]; + glm::vec2 uv3 = texture[textureIndex[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 t; + t.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x); + t.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y); + t.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z); + + glm::vec3 b; + b.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x); + b.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y); + b.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z); + + tangent[i] = t; + bitangent[i] = b; } elements.flush(); + vbo.flush(); + norm.flush(); + uvs.flush(); + tangent.flush(); + bitangent.flush(); Engine::VertexArrayObject vao; vao.setBuffer(0, vbo); vao.setBuffer(0, elements); + vao.setBuffer(1, norm); + vao.setBuffer(2, uvs); vao.bind(); + glActiveTexture(GL_TEXTURE0); + Engine::Texture textureDiff("Medieval_House_Diff.png"); + textureDiff.bind(); + + glActiveTexture(GL_TEXTURE1); + Engine::Texture textureNormal("Medieval_House_Nor.png"); + textureNormal.bind(); + Engine::ShaderProgram program; Engine::Shader vertexShader(GL_VERTEX_SHADER, Shaders::mainVert); Engine::Shader fragmentShader(GL_FRAGMENT_SHADER, Shaders::mainFrag); @@ -100,11 +171,11 @@ int main(int argc, char** argv) { program.use(); - glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)win->getWidth() / (float)win->getHeight(), 0.1f, 100.0f); + glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)win->getWidth() / (float)win->getHeight(), 0.1f, 1000.0f); glm::mat4 model = glm::mat4(1.0f); - model = glm::scale(model, glm::vec3(0.3f)); + model = glm::scale(model, glm::vec3(0.1f)); glm::mat4 view = glm::mat4(1.0f); - view = glm::translate(view, glm::vec3(0.0f, 0.0f, -100.0f)); + view = glm::translate(view, glm::vec3(0.0f, 0.0f, -100.0f)) GLint uniformModel = program.getUniformLocation("model"); GLint uniformView = program.getUniformLocation("view"); @@ -112,16 +183,18 @@ int main(int argc, char** argv) { glUniformMatrix4fv(uniformView, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(uniformProj, 1, GL_FALSE, glm::value_ptr(proj)); + + //glUniform1i(program.getUniformLocation("texture1"), 0); + //glUniform1i(program.getUniformLocation("normalMap"), 1); Clock clock; - //elements.bind(); do { clock.tick(); - float angle = clock.delta / 1000.0f; - model = glm::rotate(model, angle, glm::vec3(1.0f)); + float angle = clock.delta / 5000.0f; + model = glm::rotate(model, angle, glm::vec3(0.0f, 1.0f, 0.0f)); glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model)); - glDrawElements(GL_TRIANGLES, elements._size, GL_UNSIGNED_INT, 0); + glDrawElements(GL_TRIANGLES, faceIndex.size(), GL_UNSIGNED_INT, 0); } while (win->loop()); return 0; diff --git a/src/shader.h b/src/shader.h index 4cffcbb..705c0d7 100644 --- a/src/shader.h +++ b/src/shader.h @@ -5,25 +5,81 @@ namespace Shaders { std::string mainVert = R"( - #version 410 core + #version 420 core - layout(location = 0) in vec3 position; + layout(location = 0) in vec3 in_position; + layout(location = 1) in vec3 in_normal; + layout(location = 2) in vec2 in_uv; + layout(location = 3) in vec3 in_tangent; + layout(location = 4) in vec3 in_bitangent; uniform mat4 model; uniform mat4 view; uniform mat4 projection; + uniform vec3 lightPos = vec3(10.0, 300.0, 10.0); + uniform vec3 viewPos = vec3(1.0, 1.0, 100.0); + + out VS_OUT { + vec3 fragPos; + vec2 uv; + vec3 tangentLightPos; + vec3 tangentViewPos; + vec3 tangentFragPos; + } vs_out; + void main() { - gl_Position = projection * view * model * vec4(position, 1.0); - //gl_Position = vec4(position, 1.0); + vs_out.fragPos = vec3(model * vec4(in_position, 1.0)); + vs_out.uv = in_uv; + + mat3 normalMatrix = transpose(inverse(mat3(model))); + vec3 T = normalize(normalMatrix * in_tangent); + vec3 N = normalize(normalMatrix * in_normal); + T = normalize(T - dot(T, N) * N); + vec3 B = cross(N, T); + + mat3 TBN = transpose(mat3(T, B, N)); + + vs_out.tangentLightPos = TBN * lightPos; + vs_out.tangentViewPos = TBN * viewPos; + vs_out.tangentFragPos = TBN * vs_out.fragPos; + + gl_Position = projection * view * model * vec4(in_position, 1.0); } )"; std::string mainFrag = R"( - #version 410 core + #version 420 core + + in VS_OUT { + vec3 fragPos; + vec2 uv; + vec3 tangentLightPos; + vec3 tangentViewPos; + vec3 tangentFragPos; + } fs_in; + + layout(binding=0) uniform sampler2D diffuseMap; + layout(binding=1) uniform sampler2D normalMap; + + out vec4 fragColor; void main() { - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + vec3 normal = texture(normalMap, fs_in.uv).rgb; + normal = normalize(normal * 2.0 - 1.0); // this normal is in tangent space + + vec3 color = texture(diffuseMap, fs_in.uv).rgb; + vec3 ambient = 0.1 * color; + vec3 lightDir = normalize(fs_in.tangentLightPos - fs_in.tangentFragPos); + float diff = max(dot(lightDir, normal), 0.0); + vec3 diffuse = diff * color; + vec3 viewDir = normalize(fs_in.tangentViewPos - fs_in.tangentFragPos); + vec3 reflectDir = reflect(-lightDir, normal); + vec3 halfwayDir = normalize(lightDir + viewDir); + float spec = pow(max(dot(normal, halfwayDir), 0.0), 32.0); + + vec3 specular = vec3(0.2) * spec; + fragColor = vec4(ambient + diffuse + specular, 1.0); } )"; }