From 3a61b8495e3ed9ab8273bb2dd10c686a99e9e344 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Wed, 28 Sep 2022 08:04:24 -0400 Subject: [PATCH] Redo the lighting in the shaders --- examples/dev_testing/src/main.cpp | 6 +- include/simpleengine/gfx/light.h | 4 +- include/simpleengine/gfx/material.h | 30 ++++++-- resources/shaders/core/3d/fragment_core.glsl | 79 ++++++++++++-------- resources/shaders/core/3d/vertex_core.glsl | 32 +++++--- src/camera.cpp | 13 ++-- src/gfx/model.cpp | 21 ++++-- src/gfx/renderer.cpp | 36 +++++++-- 8 files changed, 143 insertions(+), 78 deletions(-) diff --git a/examples/dev_testing/src/main.cpp b/examples/dev_testing/src/main.cpp index 7c9fb8b..240d593 100644 --- a/examples/dev_testing/src/main.cpp +++ b/examples/dev_testing/src/main.cpp @@ -162,10 +162,6 @@ int main(int argc, char *argv[]) { 5, 6, 12, 12, 6, 13 }; - std::unordered_map>> textures; - textures.emplace(white_texture.type, std::vector>{ std::make_shared(white_texture) }); - se::gfx::Material white_material(textures, 1.f, 0.f, 0.f, 0.f, 0.f); - // Create a renderer auto renderer = std::make_shared(game.get_window(), core_shader); game.add_renderable(renderer); @@ -184,7 +180,7 @@ int main(int argc, char *argv[]) { model_comp.model.vertically_flip_tex_coords(); */ //entity.add_component("examples/dev_testing/resources/viper/viper.obj"); - entity.add_component("examples/dev_testing/resources/halo/halo.fbx"); + entity.add_component("examples/dev_testing/resources/halot/chief.fbx"); //entity.add_component("examples/dev_testing/resources/scientist/scientist.fbx"); //entity.add_component("examples/dev_testing/resources/paradigm/paradigm.fbx"); diff --git a/include/simpleengine/gfx/light.h b/include/simpleengine/gfx/light.h index 252b044..86f362a 100644 --- a/include/simpleengine/gfx/light.h +++ b/include/simpleengine/gfx/light.h @@ -18,8 +18,8 @@ namespace simpleengine::gfx { virtual void update(const float& delta_time) override { shader.use(); - shader.set_uniform_float_vec3("light_position", position, false); - shader.set_uniform_float_vec3("light_color", color, false); + shader.set_uniform_float_vec3("u_light_position", position, false); + shader.set_uniform_float_vec3("u_light_color", color, false); shader.unuse(); } diff --git a/include/simpleengine/gfx/material.h b/include/simpleengine/gfx/material.h index c024e45..c8663d5 100644 --- a/include/simpleengine/gfx/material.h +++ b/include/simpleengine/gfx/material.h @@ -12,15 +12,29 @@ namespace simpleengine::gfx { public: std::unordered_map>> textures; - float ambient_scalar; - float diffuse_scalar; - float specular_scalar; - float shine; - float reflectivity; + float ambient_strength; + float diffuse_strength; - Material(std::unordered_map>> textures, float shine = 1.f, float reflectivity = 0.f, float specular_scalar = 0.f, float ambient_scalar = 0.f, float diffuse_scalar = 0.f) : - textures(textures), ambient_scalar(ambient_scalar), diffuse_scalar(diffuse_scalar), specular_scalar(specular_scalar), - shine(shine), reflectivity(reflectivity) { + /** + * @brief This strengthens the brightness of a specular highlight. + * + */ + float specular_strength; + + /** + * @brief The shininess value of the highlight. (Radius of specular highlight?) + + * The higher the shininess value of an object, the more it properly reflects the light + * instead of scattering it all around and thus the smaller the highlight becomes. + * + * The shader multiplies this by 32 to get the specular highlight. + * + */ + 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) : + textures(textures), ambient_strength(ambient_scalar), diffuse_strength(diffuse_scalar), specular_strength(specular_scalar), + shine_factor(shine) { } }; diff --git a/resources/shaders/core/3d/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl index e696f2b..add12b2 100644 --- a/resources/shaders/core/3d/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -3,52 +3,67 @@ in vec3 vs_position; in vec3 vs_color; in vec3 vs_normal; +in vec3 vs_world_normal; // Normal in world space in vec2 vs_texcoord; in mat4 vs_transform; -in vec3 vs_to_light; -in vec3 vs_to_camera; + +in vec3 vs_view_pos; +in vec3 vs_light_pos; +in vec3 vs_frag_pos; const int SAMP_DIFFUSE = 0; -uniform sampler2D u_samplers[16]; -uniform float u_texture_shine[16]; -uniform float u_texture_reflectivity[16]; +const int SAMP_SPECULAR = 1; -uniform vec3 light_color; +struct Material { + sampler2D diffuse; + sampler2D specular_map; + + float ambient_strength; + float diffuse_strength; + float specular_strength; + + float shine_factor; +}; + +uniform Material u_material; + +uniform vec3 u_light_color; out vec4 fs_color; -vec3 calculate_specular(vec3 unit_normal, float shine_damper, float reflectivity); +vec3 calculate_lighting(); void main() { - // Lighting - vec3 unit_normal = normalize(vs_normal); - vec3 unit_light_vector = normalize(vs_to_light); - - float dot_prod = dot(unit_normal, unit_light_vector); - float brightness = max(dot_prod, 0.f); - vec3 diffuse = brightness * light_color; - - // Calculate the specular - float shine_damper = u_texture_shine[SAMP_DIFFUSE]; - float reflectivity = u_texture_reflectivity[SAMP_DIFFUSE]; - vec3 final_specular = calculate_specular(unit_normal, shine_damper, reflectivity); + // Combine diffuse lighting, specular, and the texture into one color. - fs_color = vec4(diffuse, 1.f) * texture(u_samplers[SAMP_DIFFUSE], vs_texcoord) + vec4(final_specular, 1.f); + //fs_color = vec4(diffuse, 1.f) * texture(u_material.diffuse, vs_texcoord) + vec4(final_specular, 1.f); + + vec3 lighting = calculate_lighting(); + + fs_color = vec4(lighting, 1.f) * texture(u_material.diffuse, vs_texcoord); } -vec3 calculate_specular(vec3 unit_normal, float shine_damper, float reflectivity) { - vec3 final_specular = vec3(0.f); - if (reflectivity > 0) { - vec3 unit_vector_to_camera = normalize(vs_to_camera); - vec3 light_direction = -unit_vector_to_camera; - vec3 reflected_light_dir = reflect(light_direction, unit_normal); - float specular_factor = dot(reflected_light_dir, unit_vector_to_camera); - specular_factor = max(specular_factor, 0.f); - float damped_specular = pow(specular_factor, shine_damper); - final_specular = damped_specular * reflectivity * light_color; - } +vec3 calculate_lighting() { + // Ambient + //float ambient_strength = 0.1; + vec3 ambient = u_material.ambient_strength * u_light_color; - return final_specular; + // Diffuse + vec3 norm = normalize(vs_world_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; + + //specular = specular * vec3(texture(u_material.specular_map, vs_texcoord)); // TODO check if its set before applying it. + + return ambient + diffuse + specular; } \ No newline at end of file diff --git a/resources/shaders/core/3d/vertex_core.glsl b/resources/shaders/core/3d/vertex_core.glsl index f880358..6efa103 100644 --- a/resources/shaders/core/3d/vertex_core.glsl +++ b/resources/shaders/core/3d/vertex_core.glsl @@ -8,29 +8,37 @@ layout (location = 3) in vec2 vertex_texcoord; out vec3 vs_position; out vec3 vs_color; out vec3 vs_normal; +out vec3 vs_world_normal; // normal in world space out vec2 vs_texcoord; out mat4 vs_transform; -out vec3 vs_to_light; -out vec3 vs_to_camera; -uniform mat4 transform_matrix; -uniform mat4 view_matrix; -uniform mat4 projection_matrix; -uniform vec3 light_position; +out vec3 vs_view_pos; +out vec3 vs_light_pos; +out vec3 vs_frag_pos; + +uniform mat4 u_transform_matrix; +uniform mat4 u_view_matrix; +uniform mat4 u_projection_matrix; + +uniform vec3 u_view_pos; +uniform vec3 u_light_position; void main() { - vec4 world_pos = (transform_matrix * vec4(vertex_position, 1.f)); + vec4 world_pos = (u_transform_matrix * vec4(vertex_position, 1.f)); // Directly pass things to the fragment shader. vs_position = world_pos.xyz; - vs_transform = transform_matrix; + vs_transform = u_transform_matrix; vs_texcoord = vertex_texcoord; vs_color = vertex_color; - gl_Position = projection_matrix * view_matrix * world_pos; + gl_Position = u_projection_matrix * u_view_matrix * world_pos; - vs_normal = (transform_matrix * vec4(vertex_normal, 0.f)).xyz; - vs_to_light = light_position - world_pos.xyz; - vs_to_camera = (inverse(view_matrix) * vec4(0.f, 0.f, 0.f, 1.f)).xyz - world_pos.xyz; + vs_normal = (u_transform_matrix * vec4(vertex_normal, 0.f)).xyz; + + vs_view_pos = u_view_pos; + vs_light_pos = u_light_position; + 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 } \ No newline at end of file diff --git a/src/camera.cpp b/src/camera.cpp index 5400a5c..64236f0 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -63,19 +63,19 @@ namespace simpleengine { } if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) { - rotation.z += camera_speed * .3; + rotation.z += camera_speed * .4; } if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) { - rotation.z -= camera_speed * .3; + rotation.z -= camera_speed * .4; } if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) { - rotation.y -= camera_speed * .3; + rotation.y -= camera_speed * .4; } if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) { - rotation.y += camera_speed * .3; + rotation.y += camera_speed * .4; } // Limit the pitch of the camera. @@ -96,8 +96,9 @@ namespace simpleengine { view_matrix = glm::lookAt(position, position + camera_front, camera_up); shader.use(); - shader.set_uniform_matrix_4f("view_matrix", view_matrix, false); - shader.set_uniform_matrix_4f("projection_matrix", projection_matrix, false); + shader.set_uniform_float_vec3("u_view_pos", position, false); + shader.set_uniform_matrix_4f("u_view_matrix", view_matrix, false); + shader.set_uniform_matrix_4f("u_projection_matrix", projection_matrix, false); shader.unuse(); } } \ No newline at end of file diff --git a/src/gfx/model.cpp b/src/gfx/model.cpp index 346828a..ae7beb9 100644 --- a/src/gfx/model.cpp +++ b/src/gfx/model.cpp @@ -101,7 +101,7 @@ namespace simpleengine::gfx { auto white_texture = gfx::Texture::white_texture(); std::unordered_map>> default_textures; default_textures.emplace(white_texture.type, std::vector>{ std::make_shared(white_texture) }); - gfx::Material mat(default_textures, 1.f, 0.f, 0.f, 0.f, 0.f); + gfx::Material mat(default_textures); if (mesh->mMaterialIndex >= 0) { std::cout << "TODO: Process model materials!" << std::endl; @@ -110,14 +110,25 @@ namespace simpleengine::gfx { aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; // Load Diffuse texture maps - std::vector> diffuse_maps = load_material_texture(processed_textures, material, aiTextureType_DIFFUSE); - if (!diffuse_maps.empty()) textures.emplace(aiTextureType_DIFFUSE, diffuse_maps); + aiTextureType loading_type = aiTextureType_DIFFUSE; + std::vector> diffuse_maps = load_material_texture(processed_textures, material, loading_type); + if (!diffuse_maps.empty()) textures.emplace(loading_type, diffuse_maps); + + // Load specular texture maps + loading_type = aiTextureType_SPECULAR; + std::vector> spec_maps = load_material_texture(processed_textures, material, loading_type); + if (!spec_maps.empty()) textures.emplace(loading_type, spec_maps); + + // Load normals texture maps + loading_type = aiTextureType_NORMALS; + std::vector> normal_maps = load_material_texture(processed_textures, material, loading_type); + if (!normal_maps.empty()) textures.emplace(loading_type, normal_maps); // TODO Handle other types of texture maps if (!textures.empty()) { // TODO: Find a way to let the user set the scalars. - mat = Material(textures, 1.f, 0.f, 0.f, 0.f, 0.f); + mat = Material(textures); // Add `textures` into the `processed_textures` list. for (const auto& pair : textures) { @@ -186,7 +197,7 @@ namespace simpleengine::gfx { ss << model_directory << "/" << texture_path; std::string full_path = ss.str(); - Texture texture(full_path.c_str(), type, /* TextureFlags::TexFlags_FLIP_VERTICALLY | */ TextureFlags::TexFlags_IMG_2D | TextureFlags::TexFlags_MIPMAP); + Texture texture(full_path.c_str(), type, TextureFlags::TexFlags_IMG_2D | TextureFlags::TexFlags_MIPMAP); texture.path = texture_path; textures.emplace_back(std::make_shared(texture)); diff --git a/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index 7368ff9..826ed7d 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -93,19 +93,39 @@ namespace simpleengine::gfx { RenderingJob& job = rendering_queue.front(); Mesh& mesh = job.rendering_mesh; - shader.set_uniform_matrix_4f("transform_matrix", job.transform_mat, false); + shader.set_uniform_matrix_4f("u_transform_matrix", job.transform_mat, false); std::optional& material = mesh.material; - shader.set_uniform_int("u_textures", 0, false); - if (material.has_value()) { - shader.set_uniform_float("u_texture_shine", material->shine, false); - shader.set_uniform_float("u_texture_reflectivity", material->reflectivity, false); + shader.set_uniform_float("u_material.ambient_strength", material->ambient_strength, false); + shader.set_uniform_float("u_material.diffuse_strength", material->diffuse_strength, false); + shader.set_uniform_float("u_material.specular_strength", material->specular_strength, false); + shader.set_uniform_float("u_material.shine_factor", material->shine_factor, false); + //shader.set_uniform_float("u_material.reflect_factor", .1f, false); - int texture_count = 0; auto diffuse_maps = material->textures.find(aiTextureType_DIFFUSE); - for (const auto& texture : diffuse_maps->second) { + auto diffuse_map = diffuse_maps->second.front(); + + shader.set_uniform_int("u_material.diffuse", 0, false); + + glActiveTexture(GL_TEXTURE0); + diffuse_map->bind(); + + auto specular_maps = material->textures.find(aiTextureType_SPECULAR); + + + if (specular_maps != material->textures.end()) { + auto spec = specular_maps->second.front(); + + shader.set_uniform_int("u_material.specular_map", 1, false); + + glActiveTexture(GL_TEXTURE1); + spec->bind(); + } + + //diffuse_map + /* for (const auto& texture : diffuse_maps->second) { // We can only bind to 16 textures at a time (indexes are 0-15) if (texture_count >= 16) break; @@ -113,7 +133,7 @@ namespace simpleengine::gfx { glBindTextureUnit(texture_count, texture->get_texture_id()); texture_count++; - } + } */ } mesh.vao.bind();