Redo the normal map lighting to be done in tangent space and with blinn-phong lighing

This commit is contained in:
SeanOMik 2022-10-02 11:39:07 -04:00
parent 366ab19544
commit 19d116ef65
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
9 changed files with 107 additions and 102 deletions

View File

@ -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 WarningsAsErrors: true
HeaderFilterRegex: '' HeaderFilterRegex: ""
AnalyzeTemporaryDtors: false AnalyzeTemporaryDtors: false
FormatStyle: google FormatStyle: google
CheckOptions: CheckOptions:
- key: cert-dcl16-c.NewSuffixes - key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU' value: "L;LL;LU;LLU"
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
value: '0' value: "0"
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
value: '1' value: "1"
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: '1' value: "1"
- key: google-readability-braces-around-statements.ShortStatementLines - key: google-readability-braces-around-statements.ShortStatementLines
value: '1' value: "1"
- key: google-readability-function-size.StatementThreshold - key: google-readability-function-size.StatementThreshold
value: '800' value: "800"
- key: google-readability-namespace-comments.ShortNamespaceLines - key: google-readability-namespace-comments.ShortNamespaceLines
value: '10' value: "10"
- key: google-readability-namespace-comments.SpacesBeforeComments - key: google-readability-namespace-comments.SpacesBeforeComments
value: '2' value: "2"
- key: modernize-loop-convert.MaxCopySize - key: modernize-loop-convert.MaxCopySize
value: '16' value: "16"
- key: modernize-loop-convert.MinConfidence - key: modernize-loop-convert.MinConfidence
value: reasonable value: reasonable
- key: modernize-loop-convert.NamingStyle - key: modernize-loop-convert.NamingStyle
value: CamelCase value: CamelCase
- key: modernize-pass-by-value.IncludeStyle - key: modernize-pass-by-value.IncludeStyle
value: llvm value: llvm
- key: modernize-replace-auto-ptr.IncludeStyle - key: modernize-replace-auto-ptr.IncludeStyle
value: llvm value: llvm
- key: modernize-use-nullptr.NullMacros - key: modernize-use-nullptr.NullMacros
value: 'NULL' value: "NULL"
... - key: readability-magic-numbers
value: "0"
---

View File

@ -179,7 +179,7 @@ int main(int argc, char *argv[]) {
// entity.add_component<se::ModelComponent>("examples/dev_testing/resources/paradigm/paradigm.fbx"); // entity.add_component<se::ModelComponent>("examples/dev_testing/resources/paradigm/paradigm.fbx");
// entity.add_component<se::RotatingComponent>(); // entity.add_component<se::RotatingComponent>();
auto &transform_comp = entity.add_component<se::TransformComponent>(); auto &transform_comp = entity.add_component<se::TransformComponent>();
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.scale(0.05f);
// transform_comp.rotate_z(-90.f); // transform_comp.rotate_z(-90.f);
// transform_comp.rotate_y(-90.f); // transform_comp.rotate_y(-90.f);
@ -197,7 +197,7 @@ int main(int argc, char *argv[]) {
auto camera = std::make_shared<se::Camera>(game.get_window(), core_shader, 70, glm::vec3(0, 0, 0)); auto camera = std::make_shared<se::Camera>(game.get_window(), core_shader, 70, glm::vec3(0, 0, 0));
game.add_event(camera); game.add_event(camera);
auto light = std::make_shared<se::gfx::Light>(core_shader, glm::vec3(-10.f, 0.f, 0.f), glm::vec3(1.f, 1.f, 1.f)); auto light = std::make_shared<se::gfx::Light>(core_shader, glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.f, 1.f, 1.f));
game.add_event(light); game.add_event(light);
auto fps_counter = std::make_shared<FPSCounterEvent>(); auto fps_counter = std::make_shared<FPSCounterEvent>();

View File

@ -32,7 +32,7 @@ namespace simpleengine::gfx {
*/ */
float shine_factor; float shine_factor;
Material(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>> textures, float shine = 1.f, float specular_scalar = 1.f, float ambient_scalar = 0.2f, float diffuse_scalar = 1.f) : Material(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>> 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), textures(textures), ambient_strength(ambient_scalar), diffuse_strength(diffuse_scalar), specular_strength(specular_scalar),
shine_factor(shine) { shine_factor(shine) {

View File

@ -25,22 +25,16 @@ namespace simpleengine::gfx {
std::vector<GLuint> indicies; std::vector<GLuint> indicies;
std::vector<simpleengine::Vectorf> tangents; std::vector<simpleengine::Vectorf> tangents;
std::vector<simpleengine::Vectorf> bitangents; gfx::VBO tangent_vbo;
bool are_buffers_created = false; bool are_buffers_created = false;
gfx::VBO ebo; gfx::VBO ebo;
gfx::VBO vbo; gfx::VBO vbo;
gfx::VAO vao; gfx::VAO vao;
gfx::VBO tangent_vbo;
//gfx::VAO tangent_vao;
gfx::VBO bitangent_vbo;
//gfx::VAO bitangent_vao;
Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material); Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material);
Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies = std::vector<GLuint>(), std::optional<Material> material = std::nullopt); Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies = std::vector<GLuint>(), std::optional<Material> material = std::nullopt);
Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao, gfx::VBO tangent_vbo, gfx::VBO bitangent_vbo); Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao, gfx::VBO tangent_vbo);
virtual void destroy() override; virtual void destroy() override;

View File

@ -12,7 +12,11 @@ in vec3 vs_view_pos;
in vec3 vs_light_pos; in vec3 vs_light_pos;
in vec3 vs_frag_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_DIFFUSE = 0;
const int SAMP_SPECULAR = 1; const int SAMP_SPECULAR = 1;
@ -50,32 +54,34 @@ void main() {
} }
vec3 calculate_lighting() { vec3 calculate_lighting() {
// Ambient vec3 normal = vec3(0.f, 0.f, 1.f); // default tangent-space normal
//float ambient_strength = 0.1;
vec3 ambient = u_material.ambient_strength * u_light_color;
vec3 normal = vs_world_normal;
// Check if the normal map is set before trying to apply it. // Check if the normal map is set before trying to apply it.
if (u_material.has_normal_map) { if (u_material.has_normal_map) {
normal = texture(u_material.normal_map, vs_texcoord).rgb; 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 // Get diffuse color
vec3 norm = normalize(normal); vec3 diffuse_map = texture(u_material.diffuse, vs_texcoord).rgb;
vec3 light_dir = normalize(vs_light_pos - vs_frag_pos);
float diff = max(dot(norm, light_dir), 0.f); // Ambient lighting
vec3 diffuse = (diff * u_material.diffuse_strength) * u_light_color; vec3 ambient = 0.1f * u_material.ambient_strength * diffuse_map;
// Specular // Diffuse lighting
float specular_strength = 0.5; vec3 light_dir = normalize(vs_tangent_light_pos - vs_tangent_frag_pos);
vec3 view_dir = normalize(vs_view_pos - vs_frag_pos); float diff = max(dot(light_dir, normal), 0.f);
vec3 reflect_dir = reflect(-light_dir, norm); vec3 diffuse = diff * u_material.diffuse_strength * diffuse_map;
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; // 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. // Check if the specular map is set before trying to apply it.
if (u_material.has_specular_map) { if (u_material.has_specular_map) {
specular = specular * texture(u_material.specular_map, vs_texcoord).r; specular = specular * texture(u_material.specular_map, vs_texcoord).r;

View File

@ -6,7 +6,6 @@ layout (location = 2) in vec3 vertex_normal;
layout (location = 3) in vec2 vertex_texcoord; layout (location = 3) in vec2 vertex_texcoord;
// TODO: Make these optional // TODO: Make these optional
layout (location = 4) in vec3 vertex_tangent; layout (location = 4) in vec3 vertex_tangent;
layout (location = 5) in vec3 vertex_bitangent;
out vec3 vs_position; out vec3 vs_position;
out vec3 vs_color; out vec3 vs_color;
@ -20,7 +19,11 @@ out vec3 vs_view_pos;
out vec3 vs_light_pos; out vec3 vs_light_pos;
out vec3 vs_frag_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_transform_matrix;
uniform mat4 u_view_matrix; uniform mat4 u_view_matrix;
@ -40,6 +43,7 @@ void main() {
gl_Position = u_projection_matrix * u_view_matrix * world_pos; 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_normal = (u_transform_matrix * vec4(vertex_normal, 0.f)).xyz;
vs_view_pos = u_view_pos; 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_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 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) // Calculate tangent space stuff.
vec3 T = normalize(vec3(u_transform_matrix * vec4(vertex_tangent, 1.f))); mat3 normal_matrix = transpose(inverse(mat3(u_transform_matrix)));
vec3 B = normalize(vec3(u_transform_matrix * vec4(vertex_bitangent, 1.f))); vec3 T = normalize(normal_matrix * vertex_tangent);
vec3 N = normalize(vec3(u_transform_matrix * vec4(vertex_normal, 1.f))); vec3 N = normalize(normal_matrix * vertex_normal);
vs_tbn = mat3(T, B, N); 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;
} }

View File

@ -7,20 +7,20 @@ namespace simpleengine::gfx {
Mesh::Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material) : Mesh::Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material) :
material(std::make_optional(material)), vertices(vertices), indicies(indicies), 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)), 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<LitVertex> vertices, std::vector<GLuint> indicies, std::optional<Material> material) : Mesh::Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, std::optional<Material> material) :
material(material), vertices(vertices), indicies(indicies), material(material), vertices(vertices), indicies(indicies),
vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)), 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<LitVertex> vertices, std::vector<GLuint> indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao, Mesh::Mesh(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, Material material, gfx::VBO ebo, gfx::VBO vbo, gfx::VAO vao,
gfx::VBO tangent_vbo, gfx::VBO bitangent_vbo) : gfx::VBO tangent_vbo) :
vertices(vertices), indicies(indicies), material(material), ebo(ebo), vbo(vbo), vao(vao), tangent_vbo(tangent_vbo), bitangent_vbo(bitangent_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() { void Mesh::calculate_tangents() {
// Resize the tangent and bitangents // Resize the tangents vector, they will overwritten,
//tangents.clear(); // so no need to clear the vector.
tangents.resize(vertices.size()); tangents.resize(vertices.size());
//bitangents.clear();
bitangents.resize(vertices.size());
/* std::vector<simpleengine::Vectorf> tangents;
std::vector<simpleengine::Vectorf> bitangents; */
for (int i = 0; i < indicies.size(); i += 3) { for (int i = 0; i < indicies.size(); i += 3) {
int index0 = indicies[i]; int index0 = indicies[i];
@ -111,20 +107,12 @@ namespace simpleengine::gfx {
glm::vec2 delta_uv2 = lit_vertex2.tex_coord - lit_vertex0.tex_coord; 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); 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 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 bitangent = (delta_pos2 * delta_uv1.x - delta_pos1 * delta_uv2.x)*r;
tangents[index0] = tangent; tangents[index0] = tangent;
tangents[index1] = tangent; tangents[index1] = tangent;
tangents[index2] = tangent; tangents[index2] = tangent;
bitangents[index0] = bitangent;
bitangents[index1] = bitangent;
bitangents[index2] = bitangent;
} }
/* this->tangents = std::optional<std::pair<std::vector<simpleengine::Vectorf>, std::vector<simpleengine::Vectorf>>>(
{tangents, bitangents}
); */
} }
} }

View File

@ -28,18 +28,17 @@ namespace simpleengine::gfx {
if (model_processing_flags & ModelProcessingFlags::MdlProcFlag_FLIP_TEX_COORDS_HORIZONTALLY) { if (model_processing_flags & ModelProcessingFlags::MdlProcFlag_FLIP_TEX_COORDS_HORIZONTALLY) {
horizontally_flip_tex_coords(); horizontally_flip_tex_coords();
} }
if (model_processing_flags & ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE) {
calculate_tangents();
}
} }
void Model::load_model(std::string path) { void Model::load_model(std::string path) {
Assimp::Importer importer; 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 // 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 const aiScene *scene = importer.ReadFile(path, additional_assimp_flags | aiProcess_Triangulate | aiProcess_FlipUVs);
| aiProcess_CalcTangentSpace);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl; std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl;
@ -70,6 +69,7 @@ namespace simpleengine::gfx {
gfx::Mesh Model::process_mesh(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>>& processed_textures, aiMesh* mesh, const aiScene* scene) { gfx::Mesh Model::process_mesh(std::unordered_map<aiTextureType, std::vector<std::shared_ptr<Texture>>>& processed_textures, aiMesh* mesh, const aiScene* scene) {
std::vector<LitVertex> vertices; std::vector<LitVertex> vertices;
std::vector<unsigned int> indicies; std::vector<unsigned int> indicies;
std::vector<Vectorf> tangents;
for (unsigned int i = 0; i < mesh->mNumVertices; i++) { for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
LitVertex vertex; LitVertex vertex;
@ -91,6 +91,10 @@ namespace simpleengine::gfx {
vertex.tex_coord = tex_coord; 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); vertices.push_back(vertex);
} }
@ -173,6 +177,10 @@ namespace simpleengine::gfx {
se_mesh.calculate_normals(); se_mesh.calculate_normals();
} }
if (mesh->HasTangentsAndBitangents()) {
se_mesh.tangents = tangents;
}
return se_mesh; return se_mesh;
} }

View File

@ -64,9 +64,6 @@ namespace simpleengine::gfx {
rendering_mesh.tangent_vbo.buffer(rendering_mesh.tangents.data(), 0, rendering_mesh.tangents.size() * sizeof(Vectorf)); 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); 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(); vbo.unbind();
vao.unbind(); vao.unbind();