From 19d116ef659f67b5de4ae519bf2976c056313a92 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sun, 2 Oct 2022 11:39:07 -0400 Subject: [PATCH] Redo the normal map lighting to be done in tangent space and with blinn-phong lighing --- .clang-tidy | 66 ++++++++++---------- examples/dev_testing/src/main.cpp | 4 +- include/simpleengine/gfx/material.h | 2 +- include/simpleengine/gfx/mesh.h | 10 +-- resources/shaders/core/3d/fragment_core.glsl | 52 ++++++++------- resources/shaders/core/3d/vertex_core.glsl | 24 ++++--- src/gfx/mesh.cpp | 28 +++------ src/gfx/model.cpp | 20 ++++-- src/gfx/renderer.cpp | 3 - 9 files changed, 107 insertions(+), 102 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 66b1807..b3fa1d3 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,37 +1,39 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,modernize-*,-modernize-use-trailing-return-type' +Checks: "clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,modernize-*,-modernize-use-trailing-return-type" WarningsAsErrors: true -HeaderFilterRegex: '' +HeaderFilterRegex: "" AnalyzeTemporaryDtors: false -FormatStyle: google +FormatStyle: google CheckOptions: - - key: cert-dcl16-c.NewSuffixes - value: 'L;LL;LU;LLU' - - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField - value: '0' - - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors - value: '1' - - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic - value: '1' - - key: google-readability-braces-around-statements.ShortStatementLines - value: '1' - - key: google-readability-function-size.StatementThreshold - value: '800' - - key: google-readability-namespace-comments.ShortNamespaceLines - value: '10' - - key: google-readability-namespace-comments.SpacesBeforeComments - value: '2' - - key: modernize-loop-convert.MaxCopySize - value: '16' - - key: modernize-loop-convert.MinConfidence - value: reasonable - - key: modernize-loop-convert.NamingStyle - value: CamelCase - - key: modernize-pass-by-value.IncludeStyle - value: llvm - - key: modernize-replace-auto-ptr.IncludeStyle - value: llvm - - key: modernize-use-nullptr.NullMacros - value: 'NULL' -... + - key: cert-dcl16-c.NewSuffixes + value: "L;LL;LU;LLU" + - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: "0" + - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: "1" + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: "1" + - key: google-readability-braces-around-statements.ShortStatementLines + value: "1" + - key: google-readability-function-size.StatementThreshold + value: "800" + - key: google-readability-namespace-comments.ShortNamespaceLines + value: "10" + - key: google-readability-namespace-comments.SpacesBeforeComments + value: "2" + - key: modernize-loop-convert.MaxCopySize + value: "16" + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-use-nullptr.NullMacros + value: "NULL" + - key: readability-magic-numbers + value: "0" +--- diff --git a/examples/dev_testing/src/main.cpp b/examples/dev_testing/src/main.cpp index 0b11aa1..901cb11 100644 --- a/examples/dev_testing/src/main.cpp +++ b/examples/dev_testing/src/main.cpp @@ -179,7 +179,7 @@ int main(int argc, char *argv[]) { // entity.add_component("examples/dev_testing/resources/paradigm/paradigm.fbx"); // entity.add_component(); auto &transform_comp = entity.add_component(); - transform_comp.translate(7.f, 0.f, 0.f); + transform_comp.translate(4.f, 0.f, 0.f); // transform_comp.scale(0.05f); // transform_comp.rotate_z(-90.f); // transform_comp.rotate_y(-90.f); @@ -197,7 +197,7 @@ int main(int argc, char *argv[]) { auto camera = std::make_shared(game.get_window(), core_shader, 70, glm::vec3(0, 0, 0)); game.add_event(camera); - auto light = std::make_shared(core_shader, glm::vec3(-10.f, 0.f, 0.f), glm::vec3(1.f, 1.f, 1.f)); + auto light = std::make_shared(core_shader, glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.f, 1.f, 1.f)); game.add_event(light); auto fps_counter = std::make_shared(); diff --git a/include/simpleengine/gfx/material.h b/include/simpleengine/gfx/material.h index c8663d5..50077d7 100644 --- a/include/simpleengine/gfx/material.h +++ b/include/simpleengine/gfx/material.h @@ -32,7 +32,7 @@ namespace simpleengine::gfx { */ float shine_factor; - Material(std::unordered_map>> textures, float shine = 1.f, float specular_scalar = 1.f, float ambient_scalar = 0.2f, float diffuse_scalar = 1.f) : + Material(std::unordered_map>> textures, float shine = 1.f, float specular_scalar = 1.f, float ambient_scalar = 1.f, float diffuse_scalar = 1.f) : textures(textures), ambient_strength(ambient_scalar), diffuse_strength(diffuse_scalar), specular_strength(specular_scalar), shine_factor(shine) { diff --git a/include/simpleengine/gfx/mesh.h b/include/simpleengine/gfx/mesh.h index 716e326..abf9c2e 100644 --- a/include/simpleengine/gfx/mesh.h +++ b/include/simpleengine/gfx/mesh.h @@ -25,22 +25,16 @@ namespace simpleengine::gfx { std::vector indicies; std::vector tangents; - std::vector bitangents; + gfx::VBO tangent_vbo; bool are_buffers_created = false; gfx::VBO ebo; gfx::VBO vbo; gfx::VAO vao; - gfx::VBO tangent_vbo; - //gfx::VAO tangent_vao; - - gfx::VBO bitangent_vbo; - //gfx::VAO bitangent_vao; - Mesh(std::vector vertices, std::vector indicies, Material material); Mesh(std::vector vertices, std::vector indicies = std::vector(), std::optional material = std::nullopt); - Mesh(std::vector vertices, std::vector indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao, gfx::VBO tangent_vbo, gfx::VBO bitangent_vbo); + Mesh(std::vector vertices, std::vector indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao, gfx::VBO tangent_vbo); virtual void destroy() override; diff --git a/resources/shaders/core/3d/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl index 218f012..9801a5f 100644 --- a/resources/shaders/core/3d/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -12,7 +12,11 @@ in vec3 vs_view_pos; in vec3 vs_light_pos; in vec3 vs_frag_pos; -in mat3 vs_tbn; +//in mat3 vs_tbn; + +in vec3 vs_tangent_light_pos; +in vec3 vs_tangent_view_pos; +in vec3 vs_tangent_frag_pos; const int SAMP_DIFFUSE = 0; const int SAMP_SPECULAR = 1; @@ -50,32 +54,34 @@ void main() { } vec3 calculate_lighting() { - // Ambient - //float ambient_strength = 0.1; - vec3 ambient = u_material.ambient_strength * u_light_color; - - vec3 normal = vs_world_normal; - + vec3 normal = vec3(0.f, 0.f, 1.f); // default tangent-space normal + // Check if the normal map is set before trying to apply it. if (u_material.has_normal_map) { normal = texture(u_material.normal_map, vs_texcoord).rgb; - normal = normal * 2.0 - 1.0; - normal = normalize(vs_tbn * normal); + + // transform normal vector to range [-1,1] + normal = normalize(normal * 2.f - 1.f); // this normal is in tangent space } - - // Diffuse - vec3 norm = normalize(normal); - vec3 light_dir = normalize(vs_light_pos - vs_frag_pos); - float diff = max(dot(norm, light_dir), 0.f); - vec3 diffuse = (diff * u_material.diffuse_strength) * u_light_color; - - // Specular - float specular_strength = 0.5; - vec3 view_dir = normalize(vs_view_pos - vs_frag_pos); - vec3 reflect_dir = reflect(-light_dir, norm); - float spec = pow(max(dot(view_dir, reflect_dir), -0.f), 32 * u_material.shine_factor); - vec3 specular = specular_strength * (spec * u_material.specular_strength) * u_light_color; - + + // Get diffuse color + vec3 diffuse_map = texture(u_material.diffuse, vs_texcoord).rgb; + + // Ambient lighting + vec3 ambient = 0.1f * u_material.ambient_strength * diffuse_map; + + // Diffuse lighting + vec3 light_dir = normalize(vs_tangent_light_pos - vs_tangent_frag_pos); + float diff = max(dot(light_dir, normal), 0.f); + vec3 diffuse = diff * u_material.diffuse_strength * diffuse_map; + + // Specular lighting + vec3 view_dir = normalize(vs_tangent_view_pos - vs_tangent_frag_pos); + vec3 reflect_dir = reflect(-light_dir, normal); + vec3 halfway_dir = normalize(light_dir + view_dir); + float spec = pow(max(dot(normal, halfway_dir), 0.f), 32.f * u_material.shine_factor); + vec3 specular = vec3(0.2f * u_material.specular_strength) * spec; + // Check if the specular map is set before trying to apply it. if (u_material.has_specular_map) { specular = specular * texture(u_material.specular_map, vs_texcoord).r; diff --git a/resources/shaders/core/3d/vertex_core.glsl b/resources/shaders/core/3d/vertex_core.glsl index 984b2d1..c64ca61 100644 --- a/resources/shaders/core/3d/vertex_core.glsl +++ b/resources/shaders/core/3d/vertex_core.glsl @@ -6,7 +6,6 @@ layout (location = 2) in vec3 vertex_normal; layout (location = 3) in vec2 vertex_texcoord; // TODO: Make these optional layout (location = 4) in vec3 vertex_tangent; -layout (location = 5) in vec3 vertex_bitangent; out vec3 vs_position; out vec3 vs_color; @@ -20,7 +19,11 @@ out vec3 vs_view_pos; out vec3 vs_light_pos; out vec3 vs_frag_pos; -out mat3 vs_tbn; +//out mat3 vs_tbn; + +out vec3 vs_tangent_light_pos; +out vec3 vs_tangent_view_pos; +out vec3 vs_tangent_frag_pos; uniform mat4 u_transform_matrix; uniform mat4 u_view_matrix; @@ -40,6 +43,7 @@ void main() { gl_Position = u_projection_matrix * u_view_matrix * world_pos; + // Apply transform matrix to normal. vs_normal = (u_transform_matrix * vec4(vertex_normal, 0.f)).xyz; vs_view_pos = u_view_pos; @@ -47,9 +51,15 @@ void main() { vs_frag_pos = vec3(u_transform_matrix * vec4(vertex_position, 1.f)); vs_world_normal = mat3(transpose(inverse(u_transform_matrix))) * vertex_normal; // TODO: Do this calculation on the CPU then send to GPU via a uniform - // Calculate the TBN (Tangent, Bi-tangent, and normal matrix) - vec3 T = normalize(vec3(u_transform_matrix * vec4(vertex_tangent, 1.f))); - vec3 B = normalize(vec3(u_transform_matrix * vec4(vertex_bitangent, 1.f))); - vec3 N = normalize(vec3(u_transform_matrix * vec4(vertex_normal, 1.f))); - vs_tbn = mat3(T, B, N); + // Calculate tangent space stuff. + mat3 normal_matrix = transpose(inverse(mat3(u_transform_matrix))); + vec3 T = normalize(normal_matrix * vertex_tangent); + vec3 N = normalize(normal_matrix * vertex_normal); + T = normalize(T - dot(T, N) * N); + vec3 B = cross(N, T); + + mat3 TBN = transpose(mat3(T, B, N)); + vs_tangent_light_pos = TBN * u_light_position; + vs_tangent_view_pos = TBN * u_view_pos; + vs_tangent_frag_pos = TBN * vs_frag_pos; } \ No newline at end of file diff --git a/src/gfx/mesh.cpp b/src/gfx/mesh.cpp index 06440bf..4c47090 100644 --- a/src/gfx/mesh.cpp +++ b/src/gfx/mesh.cpp @@ -7,20 +7,20 @@ namespace simpleengine::gfx { Mesh::Mesh(std::vector vertices, std::vector indicies, Material material) : material(std::make_optional(material)), vertices(vertices), indicies(indicies), vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)), - vao(gfx::VAO::init()), tangent_vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), bitangent_vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)) { + vao(gfx::VAO::init()), tangent_vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)) { } Mesh::Mesh(std::vector vertices, std::vector indicies, std::optional material) : material(material), vertices(vertices), indicies(indicies), vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)), - vao(gfx::VAO::init()), tangent_vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), bitangent_vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)) { + vao(gfx::VAO::init()), tangent_vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)) { } Mesh::Mesh(std::vector vertices, std::vector indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao, - gfx::VBO tangent_vbo, gfx::VBO bitangent_vbo) : - vertices(vertices), indicies(indicies), material(material), ebo(ebo), vbo(vbo), vao(vao), tangent_vbo(tangent_vbo), bitangent_vbo(bitangent_vbo) { + gfx::VBO tangent_vbo) : + vertices(vertices), indicies(indicies), material(material), ebo(ebo), vbo(vbo), vao(vao), tangent_vbo(tangent_vbo) { } @@ -81,13 +81,9 @@ namespace simpleengine::gfx { } void Mesh::calculate_tangents() { - // Resize the tangent and bitangents - //tangents.clear(); + // Resize the tangents vector, they will overwritten, + // so no need to clear the vector. tangents.resize(vertices.size()); - //bitangents.clear(); - bitangents.resize(vertices.size()); - /* std::vector tangents; - std::vector bitangents; */ for (int i = 0; i < indicies.size(); i += 3) { int index0 = indicies[i]; @@ -111,20 +107,12 @@ namespace simpleengine::gfx { glm::vec2 delta_uv2 = lit_vertex2.tex_coord - lit_vertex0.tex_coord; float r = 1.0f / (delta_uv1.x * delta_uv2.y - delta_uv1.y * delta_uv2.x); - glm::vec3 tangent = (delta_pos1 * delta_uv2.y - delta_pos2 * delta_uv1.y)*r; - glm::vec3 bitangent = (delta_pos2 * delta_uv1.x - delta_pos1 * delta_uv2.x)*r; + glm::vec3 tangent = (delta_pos1 * delta_uv2.y - delta_pos2 * delta_uv1.y)*r; + //glm::vec3 bitangent = (delta_pos2 * delta_uv1.x - delta_pos1 * delta_uv2.x)*r; tangents[index0] = tangent; tangents[index1] = tangent; tangents[index2] = tangent; - - bitangents[index0] = bitangent; - bitangents[index1] = bitangent; - bitangents[index2] = bitangent; } - - /* this->tangents = std::optional, std::vector>>( - {tangents, bitangents} - ); */ } } \ No newline at end of file diff --git a/src/gfx/model.cpp b/src/gfx/model.cpp index 89de207..8fd542c 100644 --- a/src/gfx/model.cpp +++ b/src/gfx/model.cpp @@ -28,18 +28,17 @@ namespace simpleengine::gfx { if (model_processing_flags & ModelProcessingFlags::MdlProcFlag_FLIP_TEX_COORDS_HORIZONTALLY) { horizontally_flip_tex_coords(); } - - if (model_processing_flags & ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE) { - calculate_tangents(); - } } void Model::load_model(std::string path) { Assimp::Importer importer; + if (model_processing_flags & ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE) { + additional_assimp_flags |= aiProcess_CalcTangentSpace; + } + // assimp post processing options: http://assimp.sourceforge.net/lib_html/postprocess_8h.html - const aiScene *scene = importer.ReadFile(path, additional_assimp_flags | aiProcess_Triangulate | aiProcess_FlipUVs - | aiProcess_CalcTangentSpace); + const aiScene *scene = importer.ReadFile(path, additional_assimp_flags | aiProcess_Triangulate | aiProcess_FlipUVs); if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl; @@ -70,6 +69,7 @@ namespace simpleengine::gfx { gfx::Mesh Model::process_mesh(std::unordered_map>>& processed_textures, aiMesh* mesh, const aiScene* scene) { std::vector vertices; std::vector indicies; + std::vector tangents; for (unsigned int i = 0; i < mesh->mNumVertices; i++) { LitVertex vertex; @@ -91,6 +91,10 @@ namespace simpleengine::gfx { vertex.tex_coord = tex_coord; } + if (mesh->HasTangentsAndBitangents()) { + tangents.emplace_back(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z); + } + vertices.push_back(vertex); } @@ -173,6 +177,10 @@ namespace simpleengine::gfx { se_mesh.calculate_normals(); } + if (mesh->HasTangentsAndBitangents()) { + se_mesh.tangents = tangents; + } + return se_mesh; } diff --git a/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index e336daa..336568a 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -64,9 +64,6 @@ namespace simpleengine::gfx { rendering_mesh.tangent_vbo.buffer(rendering_mesh.tangents.data(), 0, rendering_mesh.tangents.size() * sizeof(Vectorf)); vao.enable_attrib(rendering_mesh.tangent_vbo, 4, 3, GL_FLOAT, sizeof(Vectorf), 0, false); - rendering_mesh.bitangent_vbo.buffer(rendering_mesh.bitangents.data(), 0, rendering_mesh.bitangents.size() * sizeof(Vectorf)); - vao.enable_attrib(rendering_mesh.bitangent_vbo, 5, 3, GL_FLOAT, sizeof(Vectorf), 0, false); - vbo.unbind(); vao.unbind();