From f2258f41c4b97d84231e6ec790281ce824c944ac Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Tue, 27 Sep 2022 16:14:36 -0400 Subject: [PATCH 1/9] Remove the 3d-"batched" rendering --- examples/dev_testing/src/main.cpp | 20 ++++++++++++-------- resources/shaders/core/3d/fragment_core.glsl | 19 +++++++------------ resources/shaders/core/3d/vertex_core.glsl | 5 ----- src/gfx/model.cpp | 6 ++++-- 4 files changed, 23 insertions(+), 27 deletions(-) diff --git a/examples/dev_testing/src/main.cpp b/examples/dev_testing/src/main.cpp index 269f46b..7c9fb8b 100644 --- a/examples/dev_testing/src/main.cpp +++ b/examples/dev_testing/src/main.cpp @@ -77,9 +77,6 @@ int main(int argc, char *argv[]) { // Load core shaders from SimpleEngine resources se::gfx::shaders::Core3dShader core_shader; - auto light = std::make_shared(core_shader, glm::vec3(0.f, 1.f, -10.f), glm::vec3(1.f, 1.f, 1.f)); - game.add_event(light); - auto white_texture = se::gfx::Texture::white_texture(); // white_texture.shine_damper = 10; //white_texture.reflectivity = 1; @@ -183,16 +180,20 @@ int main(int argc, char *argv[]) { //entity.add_component("examples/dev_testing/resources/stall.obj"); // Backpack model required vertically flipped texture coords. - auto& model_comp = entity.add_component("examples/dev_testing/resources/backpack/backpack.obj"); - model_comp.model.vertically_flip_tex_coords(); + /* auto& model_comp = entity.add_component("examples/dev_testing/resources/backpack/backpack.obj"); + 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/scientist/scientist.fbx"); //entity.add_component("examples/dev_testing/resources/paradigm/paradigm.fbx"); //entity.add_component(); auto& transform_comp = entity.add_component(); - transform_comp.translate(15.f, -8.f, 0.f); - /* transform_comp.scale(0.1f); - transform_comp.rotate_z(-90.f);*/ + transform_comp.translate(7.f, -4.f, 0.f); + transform_comp.scale(0.05f); + //transform_comp.rotate_z(-90.f); + transform_comp.rotate_y(-90.f); transform_comp.rotate_x(-90.f); @@ -208,6 +209,9 @@ 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)); + game.add_event(light); + auto fps_counter = std::make_shared(); game.add_event(fps_counter); diff --git a/resources/shaders/core/3d/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl index 962e57b..a00c4b5 100644 --- a/resources/shaders/core/3d/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -4,7 +4,6 @@ in vec3 vs_position; in vec3 vs_color; in vec3 vs_normal; in vec2 vs_texcoord; -flat in float vs_tex_id; // < 0 is reserved for solid colored objects. in mat4 vs_transform; in vec3 vs_to_light; @@ -29,17 +28,13 @@ void main() { float brightness = max(dot_prod, 0.f); vec3 diffuse = brightness * light_color; - if (vs_tex_id > -1) { - int id = int(vs_tex_id); - - float shine_damper = u_texture_shine[id]; - float reflectivity = u_texture_reflectivity[id]; - vec3 final_specular = calculate_specular(unit_normal, shine_damper, reflectivity); - - fs_color = vec4(diffuse, 1.f) * texture(u_textures[id], vs_texcoord) + vec4(final_specular, 1.f); - } else { - fs_color = vec4(vs_color, 1.f); // We don't add any reflectivity to solid colored vectors. - } + // Calculate the specular + float shine_damper = u_texture_shine[0]; + float reflectivity = u_texture_reflectivity[0]; + 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_textures[0], vs_texcoord) + vec4(final_specular, 1.f); } vec3 calculate_specular(vec3 unit_normal, float shine_damper, float reflectivity) { diff --git a/resources/shaders/core/3d/vertex_core.glsl b/resources/shaders/core/3d/vertex_core.glsl index cc5d36f..f880358 100644 --- a/resources/shaders/core/3d/vertex_core.glsl +++ b/resources/shaders/core/3d/vertex_core.glsl @@ -4,13 +4,11 @@ layout (location = 0) in vec3 vertex_position; layout (location = 1) in vec3 vertex_color; layout (location = 2) in vec3 vertex_normal; layout (location = 3) in vec2 vertex_texcoord; -layout (location = 4) in float vertex_tex_id; out vec3 vs_position; out vec3 vs_color; out vec3 vs_normal; out vec2 vs_texcoord; -flat out float vs_tex_id; out mat4 vs_transform; out vec3 vs_to_light; @@ -30,9 +28,6 @@ void main() { vs_texcoord = vertex_texcoord; vs_color = vertex_color; - vs_tex_id = vertex_tex_id; - - gl_Position = projection_matrix * view_matrix * world_pos; vs_normal = (transform_matrix * vec4(vertex_normal, 0.f)).xyz; diff --git a/src/gfx/model.cpp b/src/gfx/model.cpp index 98d8f7a..d82f968 100644 --- a/src/gfx/model.cpp +++ b/src/gfx/model.cpp @@ -68,17 +68,19 @@ namespace simpleengine::gfx { for (unsigned int i = 0; i < mesh->mNumVertices; i++) { LitVertex vertex; vertex.color = glm::vec3(1.f); - vertex.texture_id = 0; + vertex.texture_id = 0; // TODO simpleengine::Vectorf position(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); vertex.position = position; + // Only process normals if they exist. if (mesh->HasNormals()) { glm::vec3 normal(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z); vertex.normal = normal; } - if (mesh->mTextureCoords[0]) { + // Only process texture coords if they exist. + if (mesh->HasTextureCoords(0)) { glm::vec2 tex_coord(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y); vertex.tex_coord = tex_coord; From 7f2ff589ac043235eaeb9f8872a2921e74135977 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Tue, 27 Sep 2022 16:22:04 -0400 Subject: [PATCH 2/9] Remove tex_id from Vertexes --- include/simpleengine/vertex.h | 7 +++---- resources/shaders/core/3d/fragment_core.glsl | 9 +++++---- src/gfx/model.cpp | 1 - src/gfx/renderer.cpp | 1 - 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/simpleengine/vertex.h b/include/simpleengine/vertex.h index ccbccd7..e43b2ac 100644 --- a/include/simpleengine/vertex.h +++ b/include/simpleengine/vertex.h @@ -26,22 +26,21 @@ namespace simpleengine { glm::vec3 color; glm::vec2 tex_coord; glm::vec3 normal; - float texture_id = -1.f; LitVertex() = default; LitVertex(simpleengine::Vectorf position, glm::vec3 color, glm::vec2 tex_coord, int texture_id = -1.f) : - position(position), color(color), tex_coord(tex_coord), normal(glm::vec3(0.f)), texture_id((float) texture_id) { + position(position), color(color), tex_coord(tex_coord), normal(glm::vec3(0.f)) { } LitVertex(simpleengine::Vectorf position, glm::vec3 color, glm::vec2 tex_coord, glm::vec3 normal, int texture_id = -1.f) : - position(position), color(color), tex_coord(tex_coord), normal(normal), texture_id((float) texture_id) { + position(position), color(color), tex_coord(tex_coord), normal(normal) { } LitVertex(simpleengine::Vectorf position, glm::vec2 tex_coord, glm::vec3 normal, int texture_id = -1.f) : - position(position), color(glm::vec3(1.f)), tex_coord(tex_coord), normal(normal), texture_id((float) texture_id) { + position(position), color(glm::vec3(1.f)), tex_coord(tex_coord), normal(normal) { } }; diff --git a/resources/shaders/core/3d/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl index a00c4b5..e696f2b 100644 --- a/resources/shaders/core/3d/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -9,7 +9,8 @@ in mat4 vs_transform; in vec3 vs_to_light; in vec3 vs_to_camera; -uniform sampler2D u_textures[16]; +const int SAMP_DIFFUSE = 0; +uniform sampler2D u_samplers[16]; uniform float u_texture_shine[16]; uniform float u_texture_reflectivity[16]; @@ -29,12 +30,12 @@ void main() { vec3 diffuse = brightness * light_color; // Calculate the specular - float shine_damper = u_texture_shine[0]; - float reflectivity = u_texture_reflectivity[0]; + 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_textures[0], vs_texcoord) + vec4(final_specular, 1.f); + fs_color = vec4(diffuse, 1.f) * texture(u_samplers[SAMP_DIFFUSE], vs_texcoord) + vec4(final_specular, 1.f); } vec3 calculate_specular(vec3 unit_normal, float shine_damper, float reflectivity) { diff --git a/src/gfx/model.cpp b/src/gfx/model.cpp index d82f968..346828a 100644 --- a/src/gfx/model.cpp +++ b/src/gfx/model.cpp @@ -68,7 +68,6 @@ namespace simpleengine::gfx { for (unsigned int i = 0; i < mesh->mNumVertices; i++) { LitVertex vertex; vertex.color = glm::vec3(1.f); - vertex.texture_id = 0; // TODO simpleengine::Vectorf position(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); vertex.position = position; diff --git a/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index 11f18a5..7368ff9 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -59,7 +59,6 @@ namespace simpleengine::gfx { vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, color), false); vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal), false); vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord), false); - vao.enable_attrib(vbo, 4, 1, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, texture_id), false); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); From 3a61b8495e3ed9ab8273bb2dd10c686a99e9e344 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Wed, 28 Sep 2022 08:04:24 -0400 Subject: [PATCH 3/9] 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(); From dbc12e422c3f383541db9162da9726ccb7ea7afa Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Wed, 28 Sep 2022 21:21:47 -0400 Subject: [PATCH 4/9] Get specular maps working and make them optional --- .clang-tidy | 37 ++++++ CMake/Getassimp.cmake | 13 ++ CMakeLists.txt | 9 +- cmrc | 2 +- examples/dev_testing/src/main.cpp | 123 +++++++++---------- include/simpleengine/gfx/model.h | 2 +- include/simpleengine/gfx/texture.h | 32 ++++- resources/shaders/core/3d/fragment_core.glsl | 7 +- src/gfx/model.cpp | 10 +- src/gfx/renderer.cpp | 17 +-- src/gfx/texture.cpp | 49 ++++++-- 11 files changed, 198 insertions(+), 103 deletions(-) create mode 100644 .clang-tidy create mode 100644 CMake/Getassimp.cmake diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..66b1807 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,37 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,modernize-*,-modernize-use-trailing-return-type' +WarningsAsErrors: true +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +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' +... + diff --git a/CMake/Getassimp.cmake b/CMake/Getassimp.cmake new file mode 100644 index 0000000..7438198 --- /dev/null +++ b/CMake/Getassimp.cmake @@ -0,0 +1,13 @@ +include(ExternalProject) +ExternalProject_Add(external_assimp + GIT_REPOSITORY https://github.com/assimp/assimp.git + GIT_TAG v5.2.5 + GIT_SUBMODULES_RECURSE true + GIT_PROGRESS true + CMAKE_ARGS + -D CMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR} + -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -D ASSIMP_INSTALL=NO + -D ASSIMP_BUILD_TESTS=NO +) +message("Downloaded assimp library") \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index d30ac6b..500cdae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ find_package(GLEW REQUIRED) find_package(glfw3 CONFIG REQUIRED) find_package(glm CONFIG REQUIRED) find_package(OpenGL REQUIRED) -find_package(assimp REQUIRED) +find_package(assimp CONFIG REQUIRED) # Link sources file(GLOB_RECURSE source_list src/*.cpp) @@ -45,7 +45,12 @@ target_link_libraries(simpleengine PUBLIC GLEW::GLEW) target_link_libraries(simpleengine PUBLIC glfw) target_link_libraries(simpleengine PUBLIC ${GLM_LIBRARIES}) target_link_libraries(simpleengine PUBLIC ${OPENGL_LIBRARIES}) -target_link_libraries(simpleengine PUBLIC assimp) +if(WIN32) + target_link_libraries(simpleengine PUBLIC assimp::assimp) +else() + target_link_libraries(simpleengine PUBLIC assimp) +endif() + target_link_libraries(simpleengine PRIVATE simpleengine_resources) # Include some dependencies' include directories diff --git a/cmrc b/cmrc index e386a62..a64bea5 160000 --- a/cmrc +++ b/cmrc @@ -1 +1 @@ -Subproject commit e386a629eb537d384811e598a3c96b9ca928f65e +Subproject commit a64bea50c05594c8e7cf1f08e441bb9507742e2e diff --git a/examples/dev_testing/src/main.cpp b/examples/dev_testing/src/main.cpp index 240d593..15aaf60 100644 --- a/examples/dev_testing/src/main.cpp +++ b/examples/dev_testing/src/main.cpp @@ -1,8 +1,6 @@ #include "simpleengine/camera.h" #include "simpleengine/ecs/component/mesh_component.h" -#include #include "simpleengine/ecs/component/transform_component.h" -#include #include "simpleengine/ecs/entity.h" #include "simpleengine/gfx/light.h" #include "simpleengine/gfx/material.h" @@ -11,23 +9,25 @@ #include "simpleengine/gfx/renderer.h" #include "simpleengine/gfx/texture.h" #include "simpleengine/vector.h" -#include -#include +#include +#include #include -#include #include -#include -#include #include +#include +#include +#include #include +#include +#include +#include #include #include -#include -#include #include #include +#include #include #include @@ -46,14 +46,14 @@ public: frame_count = 0; } - virtual void update(const float& delta_time) { + virtual void update(const float &delta_time) { double current_time = glfwGetTime(); frame_count++; // Check if the last print was 1 second ago. if (current_time - last_frame_time >= 1.0) { - double ms_per_frame = 1000 / (double) frame_count; - + double ms_per_frame = 1000 / (double)frame_count; + printf("%d fps, %f ms/frame\n", frame_count, ms_per_frame); frame_count = 0; last_frame_time += 1.0; @@ -61,7 +61,7 @@ public: } }; -std::string read_resource_shader(const std::string& path) { +std::string read_resource_shader(const std::string &path) { auto fs = cmrc::resource_shaders::get_filesystem(); cmrc::file vertex_file = fs.open(path); @@ -79,14 +79,12 @@ int main(int argc, char *argv[]) { auto white_texture = se::gfx::Texture::white_texture(); // white_texture.shine_damper = 10; - //white_texture.reflectivity = 1; - /* auto dragon = std::make_shared(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/dragon.obj"); - dragon->translate(0.f, -5.f, -15.f); - game.add_event(dragon); */ + // white_texture.reflectivity = 1; + /* auto dragon = std::make_shared(game.get_window(), core_shader, white_texture, + "examples/dev_testing/resources/dragon.obj"); dragon->translate(0.f, -5.f, -15.f); game.add_event(dragon); */ - /* auto cube = std::make_shared(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/cube.obj"); - cube->translate(0.f, -5.f, -15.f); - game.add_event(cube); + /* auto cube = std::make_shared(game.get_window(), core_shader, white_texture, + "examples/dev_testing/resources/cube.obj"); cube->translate(0.f, -5.f, -15.f); game.add_event(cube); se::gfx::Texture grass("examples/dev_testing/resources/grass.png"); auto terrain = std::make_shared(game.get_window(), core_shader, grass, 0, 0); @@ -94,9 +92,8 @@ int main(int argc, char *argv[]) { game.add_event(terrain); */ /* se::gfx::Texture stall_texture("examples/dev_testing/resources/stallTextureb.png"); - auto stall = std::make_shared(game.get_window(), core_shader, stall_texture, "examples/dev_testing/resources/stall.obj"); - stall->translate(10.f, -5.f, 0.f); - stall->rotate_y(90.f); + auto stall = std::make_shared(game.get_window(), core_shader, stall_texture, + "examples/dev_testing/resources/stall.obj"); stall->translate(10.f, -5.f, 0.f); stall->rotate_y(90.f); game.add_event(stall); */ /* std::vector square_vertices = { @@ -118,9 +115,8 @@ int main(int argc, char *argv[]) { game.add_event(square); */ /* se::gfx::Texture white_texture("examples/dev_testing/resources/white_texture.png"); - auto cube = std::make_shared(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/cube.obj"); - cube->translate(-1.25f, 0.f, -1.f); - game.add_event(cube); */ + auto cube = std::make_shared(game.get_window(), core_shader, white_texture, + "examples/dev_testing/resources/cube.obj"); cube->translate(-1.25f, 0.f, -1.f); game.add_event(cube); */ /* std::vector tri_vertices = { { se::Vectorf(-0.5f, -0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f) }, // top right @@ -134,36 +130,30 @@ int main(int argc, char *argv[]) { game.add_event(tri); */ std::vector cube_vertices = { - { se::Vectorf(-1.f, -1.f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f) }, - { se::Vectorf(1.f, -1.f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, - { se::Vectorf(1.f, 1.f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 0.f) }, - { se::Vectorf(-1.f, 1.f, -1.f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 0.f) }, - { se::Vectorf(-1, -1, -1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 0.f) }, + {se::Vectorf(-1.f, -1.f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f)}, + {se::Vectorf(1.f, -1.f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f)}, + {se::Vectorf(1.f, 1.f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 0.f)}, + {se::Vectorf(-1.f, 1.f, -1.f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 0.f)}, + {se::Vectorf(-1, -1, -1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 0.f)}, - { se::Vectorf(-1, -1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 1.f) }, - { se::Vectorf(1, -1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 1.f) }, - { se::Vectorf(1, 1, 1), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 1.f) }, - { se::Vectorf(-1, 1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 1.f) }, - { se::Vectorf(-1, -1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 1.f) }, + {se::Vectorf(-1, -1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 1.f)}, + {se::Vectorf(1, -1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 1.f)}, + {se::Vectorf(1, 1, 1), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 1.f)}, + {se::Vectorf(-1, 1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 1.f)}, + {se::Vectorf(-1, -1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 1.f)}, - { se::Vectorf(-1, 1, -1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, -1.f) }, - { se::Vectorf(1, 1, -1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, -1.f) }, + {se::Vectorf(-1, 1, -1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, -1.f)}, + {se::Vectorf(1, 1, -1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, -1.f)}, - { se::Vectorf(-1, 1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 2.f) }, - { se::Vectorf(1, 1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 2.f) }, + {se::Vectorf(-1, 1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 2.f)}, + {se::Vectorf(1, 1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 2.f)}, }; - std::vector cube_indicies = { - 0, 1, 5, 5, 1, 6, - 1, 2, 6, 6, 2, 7, - 2, 3, 7, 7, 3, 8, - 3, 4, 8, 8, 4, 9, - 10, 11, 0, 0, 11, 1, - 5, 6, 12, 12, 6, 13 - }; + std::vector cube_indicies = {0, 1, 5, 5, 1, 6, 1, 2, 6, 6, 2, 7, 2, 3, 7, 7, 3, 8, + 3, 4, 8, 8, 4, 9, 10, 11, 0, 0, 11, 1, 5, 6, 12, 12, 6, 13}; // Create a renderer - auto renderer = std::make_shared(game.get_window(), core_shader); + auto renderer = std::make_shared(game.get_window(), core_shader); game.add_renderable(renderer); // Create a Scene and give it the renderer @@ -172,26 +162,27 @@ int main(int argc, char *argv[]) { // Create an Entity in the Scene and add components to it. se::ecs::Entity entity = scene->create_entity(); - //entity.add_component("examples/dev_testing/resources/dragon.obj"); - //entity.add_component("examples/dev_testing/resources/stall.obj"); - + // entity.add_component("examples/dev_testing/resources/dragon.obj"); + // entity.add_component("examples/dev_testing/resources/stall.obj"); + // Backpack model required vertically flipped texture coords. - /* auto& model_comp = entity.add_component("examples/dev_testing/resources/backpack/backpack.obj"); + /* auto& model_comp = + entity.add_component("examples/dev_testing/resources/backpack/backpack.obj"); model_comp.model.vertically_flip_tex_coords(); */ - //entity.add_component("examples/dev_testing/resources/viper/viper.obj"); - entity.add_component("examples/dev_testing/resources/halot/chief.fbx"); + // entity.add_component("examples/dev_testing/resources/viper/viper.obj"); + // entity.add_component("examples/dev_testing/resources/halot/chief.fbx"); + entity.add_component("examples/dev_testing/resources/planks/planks.fbx"); - //entity.add_component("examples/dev_testing/resources/scientist/scientist.fbx"); - //entity.add_component("examples/dev_testing/resources/paradigm/paradigm.fbx"); - //entity.add_component(); - auto& transform_comp = entity.add_component(); + // entity.add_component("examples/dev_testing/resources/scientist/scientist.fbx"); + // entity.add_component("examples/dev_testing/resources/paradigm/paradigm.fbx"); + // entity.add_component(); + auto &transform_comp = entity.add_component(); transform_comp.translate(7.f, -4.f, 0.f); - transform_comp.scale(0.05f); - //transform_comp.rotate_z(-90.f); - transform_comp.rotate_y(-90.f); - transform_comp.rotate_x(-90.f); - + // transform_comp.scale(0.05f); + // transform_comp.rotate_z(-90.f); + // transform_comp.rotate_y(-90.f); + // transform_comp.rotate_x(-90.f); // Create the entity and add the model component to it. /* auto entity = std::make_shared(); @@ -212,10 +203,10 @@ int main(int argc, char *argv[]) { game.add_event(fps_counter); game.set_enable_vsync(true); - //game.set_fps_limit(120); + // game.set_fps_limit(120); int res = game.run(); renderer->destroy(); - + return res; } \ No newline at end of file diff --git a/include/simpleengine/gfx/model.h b/include/simpleengine/gfx/model.h index a49773d..db36ef4 100644 --- a/include/simpleengine/gfx/model.h +++ b/include/simpleengine/gfx/model.h @@ -38,7 +38,7 @@ namespace simpleengine::gfx { gfx::Mesh process_mesh(std::unordered_map>>& processed_textures, aiMesh* mesh, const aiScene* scene); std::unordered_map> load_all_textures(aiMaterial* material); - std::vector> load_material_texture(std::unordered_map>>& processed_textures, aiMaterial* material, aiTextureType type); + std::vector> load_material_texture(std::unordered_map>>& processed_textures, aiMaterial* material, aiTextureType type, TextureFlags texture_color); protected: void post_process(); diff --git a/include/simpleengine/gfx/texture.h b/include/simpleengine/gfx/texture.h index 302f14b..32bffab 100644 --- a/include/simpleengine/gfx/texture.h +++ b/include/simpleengine/gfx/texture.h @@ -23,6 +23,9 @@ namespace simpleengine::gfx { TexFlags_FLIP_VERTICALLY = 0b00000010, TexFlags_FLIP_HORIZONTALLY = 0b00000100, TexFlags_MIPMAP = 0b00001000, + TexFlags_NO_COLOR = 0b00010000, + TexFlags_RGB = 0b00100000, + TexFlags_RGBA = 0b01000000, }; class Texture { @@ -34,6 +37,26 @@ namespace simpleengine::gfx { Texture() = default; public: + /** + * @brief The default Texture flags not including the color. + * + * The default flags are `TexFlags_IMG_2D | TexFlags_MIPMAP` + * + * @see simpleengine::gfx::Texture::default_flags + * + */ + static constexpr int default_flags_no_color = TexFlags_IMG_2D | TexFlags_MIPMAP; + + /** + * @brief The default Texture flags including the color. + * + * The default flags are `TexFlags_IMG_2D | TexFlags_MIPMAP | TexFlags_RGBA` + * + * @see simpleengine::gfx::Texture::default_flags_no_color + * + */ + static constexpr int default_flags = default_flags_no_color | TexFlags_RGBA; + int height; int width; int channels; @@ -47,8 +70,7 @@ namespace simpleengine::gfx { * @param img_2d Whether or not the texture is 2D. * @param mipmap Whether or not to generate mipmaps for this texture. */ - Texture(const char* path, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = TextureFlags::TexFlags_IMG_2D | - TextureFlags::TexFlags_MIPMAP); + Texture(const char* path, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = Texture::default_flags); /** * @brief Construct a new Texture object from the loaded file buffer. @@ -58,8 +80,7 @@ namespace simpleengine::gfx { * @param img_2d Whether or not the texture is 2D. * @param mipmap Whether or not to generate mipmaps for this texture. */ - Texture(const unsigned char *const buffer, int buffer_length, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = TextureFlags::TexFlags_IMG_2D | - TextureFlags::TexFlags_MIPMAP); + Texture(const unsigned char *const buffer, int buffer_length, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = Texture::default_flags); /** * @brief Construct a new Texture object from the loaded file buffer. @@ -68,8 +89,7 @@ namespace simpleengine::gfx { * @param img_2d Whether or not the texture is 2D. * @param mipmap Whether or not to generate mipmaps for this texture. */ - Texture(std::vector buffer, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = TextureFlags::TexFlags_IMG_2D | - TextureFlags::TexFlags_MIPMAP); + Texture(std::vector buffer, aiTextureType type = aiTextureType::aiTextureType_DIFFUSE, int flags = Texture::default_flags); static Texture white_texture(); diff --git a/resources/shaders/core/3d/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl index add12b2..d93f7df 100644 --- a/resources/shaders/core/3d/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -17,6 +17,8 @@ const int SAMP_SPECULAR = 1; struct Material { sampler2D diffuse; + + bool has_specular_map; sampler2D specular_map; float ambient_strength; @@ -63,7 +65,10 @@ vec3 calculate_lighting() { 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. + // Check if the specular map is set before trying to set it + if (u_material.has_specular_map) { + specular = specular * texture(u_material.specular_map, vs_texcoord).r; + } return ambient + diffuse + specular; } \ No newline at end of file diff --git a/src/gfx/model.cpp b/src/gfx/model.cpp index ae7beb9..718e23a 100644 --- a/src/gfx/model.cpp +++ b/src/gfx/model.cpp @@ -111,17 +111,17 @@ namespace simpleengine::gfx { // Load Diffuse texture maps aiTextureType loading_type = aiTextureType_DIFFUSE; - std::vector> diffuse_maps = load_material_texture(processed_textures, material, loading_type); + std::vector> diffuse_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_RGBA); 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); + std::vector> spec_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_NO_COLOR); 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); + std::vector> normal_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_NO_COLOR); if (!normal_maps.empty()) textures.emplace(loading_type, normal_maps); // TODO Handle other types of texture maps @@ -170,7 +170,7 @@ namespace simpleengine::gfx { return {}; } - std::vector> Model::load_material_texture(std::unordered_map>>& processed_textures, aiMaterial* material, aiTextureType type) { + std::vector> Model::load_material_texture(std::unordered_map>>& processed_textures, aiMaterial* material, aiTextureType type, TextureFlags texture_color) { std::vector> textures; for (int i = 0; i < material->GetTextureCount(type); i++) { @@ -197,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_IMG_2D | TextureFlags::TexFlags_MIPMAP); + Texture texture(full_path.c_str(), type, Texture::default_flags_no_color | texture_color); texture.path = texture_path; textures.emplace_back(std::make_shared(texture)); diff --git a/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index 826ed7d..6377cfa 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -112,28 +112,19 @@ namespace simpleengine::gfx { glActiveTexture(GL_TEXTURE0); diffuse_map->bind(); + // Apply the specular map if it exists 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.has_specular_map", 1, false); shader.set_uniform_int("u_material.specular_map", 1, false); glActiveTexture(GL_TEXTURE1); spec->bind(); + } else { + shader.set_uniform_int("u_material.has_specular_map", 0, false); } - - //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; - - glActiveTexture(GL_TEXTURE0 + texture_count); - glBindTextureUnit(texture_count, texture->get_texture_id()); - - texture_count++; - } */ } mesh.vao.bind(); diff --git a/src/gfx/texture.cpp b/src/gfx/texture.cpp index ad0bede..4e2fc3d 100644 --- a/src/gfx/texture.cpp +++ b/src/gfx/texture.cpp @@ -1,4 +1,5 @@ #include "gfx/texture.h" +#include #define STB_IMAGE_IMPLEMENTATION #include @@ -9,6 +10,24 @@ namespace simpleengine::gfx { bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY; bool mipmap = flags & TextureFlags::TexFlags_MIPMAP; + // Get the color channel type for opengl, and get + // the channel count for loading the texture with stb_image + int gl_color_channels; + int channel_count; + if (flags & TexFlags_RGBA) { + channel_count = 4; + gl_color_channels = GL_RGBA; + } else if (flags & TexFlags_RGB) { + channel_count = 3; + gl_color_channels = GL_RGB; + } else if (flags & TexFlags_NO_COLOR) { + channel_count = 1; + gl_color_channels = GL_RED; + } else { + std::cerr << "Texture color flag is missing!! Specify TexFlags_RGBA" << std::endl; + throw std::runtime_error("Texture color flag is missing!! Specify TexFlags_RGBA"); + } + image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D; glGenTextures(1, &texture_id); @@ -23,8 +42,7 @@ namespace simpleengine::gfx { stbi_set_flip_vertically_on_load(flip_vertically); - // Read 4 channels (RGBA) - img_data = stbi_load(path, &width, &height, &channels, 4); + img_data = stbi_load(path, &width, &height, &channels, channel_count); if(!img_data) { const char* failure = stbi_failure_reason(); std::cerr << "Failed to load texture! (" << failure << ")" << std::endl; @@ -32,7 +50,7 @@ namespace simpleengine::gfx { } std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl; - glTexImage2D(image_type_gl, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data); + glTexImage2D(image_type_gl, 0, gl_color_channels, width, height, 0, gl_color_channels, GL_UNSIGNED_BYTE, img_data); if (mipmap) { glGenerateMipmap(image_type_gl); @@ -48,6 +66,24 @@ namespace simpleengine::gfx { bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY; bool mipmap = flags & TextureFlags::TexFlags_MIPMAP; + // Get the color channel type for opengl, and get + // the channel count for loading the texture with stb_image + int gl_color_channels; + int channel_count; + if (flags & TexFlags_RGBA) { + channel_count = 4; + gl_color_channels = GL_RGBA; + } else if (flags & TexFlags_RGB) { + channel_count = 3; + gl_color_channels = GL_RGB; + } else if (flags & TexFlags_NO_COLOR) { + channel_count = 1; + gl_color_channels = GL_RED; + } else { + std::cerr << "Texture color flag is missing!! Specify TexFlags_RGBA" << std::endl; + throw std::runtime_error("Texture color flag is missing!! Specify TexFlags_RGBA"); + } + image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D; glGenTextures(1, &texture_id); @@ -62,8 +98,7 @@ namespace simpleengine::gfx { stbi_set_flip_vertically_on_load(flip_vertically); - // Read 4 channels (RGBA) - img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, 4); + img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, channel_count); if(!img_data) { const char* failure = stbi_failure_reason(); std::cerr << "Failed to load texture! (" << failure << ")" << std::endl; @@ -71,7 +106,7 @@ namespace simpleengine::gfx { } std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl; - glTexImage2D(image_type_gl, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data); + glTexImage2D(image_type_gl, 0, gl_color_channels, width, height, 0, gl_color_channels, GL_UNSIGNED_BYTE, img_data); if (mipmap) { glGenerateMipmap(image_type_gl); @@ -117,8 +152,6 @@ namespace simpleengine::gfx { texture.unbind(); - - return texture; } From da3c56af362f1a57cef12c3ee378874a2b1e95d7 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Thu, 29 Sep 2022 19:13:47 -0400 Subject: [PATCH 5/9] Implement normal maps --- examples/dev_testing/src/main.cpp | 5 +- include/simpleengine/gfx/mesh.h | 19 +++++- include/simpleengine/gfx/model.h | 4 +- include/simpleengine/gfx/vao.h | 4 ++ include/simpleengine/gfx/vbo.h | 4 ++ resources/shaders/core/3d/fragment_core.glsl | 24 +++++-- resources/shaders/core/3d/vertex_core.glsl | 17 +++++ src/gfx/mesh.cpp | 59 +++++++++++++++-- src/gfx/model.cpp | 69 ++++++++++++++++++-- src/gfx/renderer.cpp | 26 +++++++- 10 files changed, 209 insertions(+), 22 deletions(-) diff --git a/examples/dev_testing/src/main.cpp b/examples/dev_testing/src/main.cpp index 15aaf60..ed4d271 100644 --- a/examples/dev_testing/src/main.cpp +++ b/examples/dev_testing/src/main.cpp @@ -172,13 +172,14 @@ int main(int argc, char *argv[]) { // entity.add_component("examples/dev_testing/resources/viper/viper.obj"); // entity.add_component("examples/dev_testing/resources/halot/chief.fbx"); - entity.add_component("examples/dev_testing/resources/planks/planks.fbx"); + //entity.add_component("examples/dev_testing/resources/planks/planks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE); + entity.add_component("examples/dev_testing/resources/bricks/bricks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE); // entity.add_component("examples/dev_testing/resources/scientist/scientist.fbx"); // entity.add_component("examples/dev_testing/resources/paradigm/paradigm.fbx"); // entity.add_component(); auto &transform_comp = entity.add_component(); - transform_comp.translate(7.f, -4.f, 0.f); + transform_comp.translate(7.f, 0.f, 0.f); // transform_comp.scale(0.05f); // transform_comp.rotate_z(-90.f); // transform_comp.rotate_y(-90.f); diff --git a/include/simpleengine/gfx/mesh.h b/include/simpleengine/gfx/mesh.h index e696053..716e326 100644 --- a/include/simpleengine/gfx/mesh.h +++ b/include/simpleengine/gfx/mesh.h @@ -8,6 +8,7 @@ #include "../renderable.h" #include "../transformable.h" #include "material.h" +#include "../vector.h" #include #include @@ -23,14 +24,23 @@ namespace simpleengine::gfx { std::vector vertices; std::vector indicies; + std::vector tangents; + std::vector bitangents; + 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); + 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); virtual void destroy() override; @@ -45,5 +55,12 @@ namespace simpleengine::gfx { * */ void calculate_normals(); + + /** + * @brief Calculate tangents and bi-tangents (tangent space) for the model. + * + * @note This **will** overwrite the existing tangents and bi-tangents. + */ + void calculate_tangents(); }; } \ No newline at end of file diff --git a/include/simpleengine/gfx/model.h b/include/simpleengine/gfx/model.h index db36ef4..4aa8a31 100644 --- a/include/simpleengine/gfx/model.h +++ b/include/simpleengine/gfx/model.h @@ -2,6 +2,7 @@ #include "mesh.h" #include "simpleengine/gfx/texture.h" +#include "../vector.h" #include #include @@ -14,6 +15,7 @@ namespace simpleengine::gfx { MdlProcFlag_NONE = 0b00000000, MdlProcFlag_FLIP_TEX_COORDS_VERTICALLY = 0b00000001, MdlProcFlag_FLIP_TEX_COORDS_HORIZONTALLY = 0b00000010, + MdlProcFlag_CALCULATE_TANGENT_SPACE = 0b00000100, }; /** @@ -39,12 +41,12 @@ namespace simpleengine::gfx { std::unordered_map> load_all_textures(aiMaterial* material); std::vector> load_material_texture(std::unordered_map>>& processed_textures, aiMaterial* material, aiTextureType type, TextureFlags texture_color); - protected: void post_process(); public: void vertically_flip_tex_coords(); void horizontally_flip_tex_coords(); + void calculate_tangents(); }; } \ No newline at end of file diff --git a/include/simpleengine/gfx/vao.h b/include/simpleengine/gfx/vao.h index f9867e0..ab7ddad 100644 --- a/include/simpleengine/gfx/vao.h +++ b/include/simpleengine/gfx/vao.h @@ -51,6 +51,10 @@ namespace simpleengine::gfx { glBindVertexArray(handle); } + void unbind() const { + glBindVertexArray(0); + } + // TODO: Fix this. void enable_attrib(const VBO& vbo, GLuint index, GLint size, GLenum type, GLsizei stride, size_t offset, bool should_bind = true) const { if (should_bind) { diff --git a/include/simpleengine/gfx/vbo.h b/include/simpleengine/gfx/vbo.h index 0148b94..a24932a 100644 --- a/include/simpleengine/gfx/vbo.h +++ b/include/simpleengine/gfx/vbo.h @@ -40,6 +40,10 @@ namespace simpleengine::gfx { glBindBuffer(type, handle); } + void unbind() const { + glBindBuffer(type, 0); + } + void buffer(void *data, size_t offset, size_t size) { bind(); glBufferData(type, size - offset, data, dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); diff --git a/resources/shaders/core/3d/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl index d93f7df..c025137 100644 --- a/resources/shaders/core/3d/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -12,6 +12,11 @@ in vec3 vs_view_pos; in vec3 vs_light_pos; in vec3 vs_frag_pos; +in mat3 vs_tbn; + +in vec3 vs_tangent; +in vec3 vs_bitangent; + const int SAMP_DIFFUSE = 0; const int SAMP_SPECULAR = 1; @@ -21,6 +26,9 @@ struct Material { bool has_specular_map; sampler2D specular_map; + // TODO: Make Optional + sampler2D normal_map; + float ambient_strength; float diffuse_strength; float specular_strength; @@ -37,14 +45,12 @@ out vec4 fs_color; vec3 calculate_lighting(); void main() { - - - // Combine diffuse lighting, specular, and the texture into one color. - //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); + //fs_color = vec4(vs_tangent, 1.f); + //fs_color = vec4(vs_bitangent, 1.f); } vec3 calculate_lighting() { @@ -52,8 +58,14 @@ vec3 calculate_lighting() { //float ambient_strength = 0.1; vec3 ambient = u_material.ambient_strength * u_light_color; + // Apply the normal map to the lighting. + vec3 normal = vs_normal; + normal = texture(u_material.normal_map, vs_texcoord).rgb; + normal = normal * 2.0 - 1.0; + normal = normalize(vs_tbn * normal); + // Diffuse - vec3 norm = normalize(vs_world_normal); + 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; diff --git a/resources/shaders/core/3d/vertex_core.glsl b/resources/shaders/core/3d/vertex_core.glsl index 6efa103..5dbace3 100644 --- a/resources/shaders/core/3d/vertex_core.glsl +++ b/resources/shaders/core/3d/vertex_core.glsl @@ -4,6 +4,9 @@ layout (location = 0) in vec3 vertex_position; layout (location = 1) in vec3 vertex_color; 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; @@ -17,6 +20,11 @@ out vec3 vs_view_pos; out vec3 vs_light_pos; out vec3 vs_frag_pos; +out mat3 vs_tbn; + +out vec3 vs_tangent; +out vec3 vs_bitangent; + uniform mat4 u_transform_matrix; uniform mat4 u_view_matrix; uniform mat4 u_projection_matrix; @@ -41,4 +49,13 @@ void main() { 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 + + // 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); + + vs_tangent = vertex_tangent; + vs_bitangent = vertex_bitangent; } \ No newline at end of file diff --git a/src/gfx/mesh.cpp b/src/gfx/mesh.cpp index ba48518..06440bf 100644 --- a/src/gfx/mesh.cpp +++ b/src/gfx/mesh.cpp @@ -1,23 +1,26 @@ #include "gfx/mesh.h" +#include "gfx/vbo.h" +#include "vector.h" #include 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()) { + vao(gfx::VAO::init()), tangent_vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), bitangent_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()) { + vao(gfx::VAO::init()), tangent_vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), bitangent_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) : - vertices(vertices), indicies(indicies), material(material), ebo(ebo), vbo(vbo), vao(vao) { + 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) { } @@ -76,4 +79,52 @@ namespace simpleengine::gfx { vertices[i].normal = normals[i]; } } + + void Mesh::calculate_tangents() { + // Resize the tangent and bitangents + //tangents.clear(); + 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]; + int index1 = indicies[i+1]; + int index2 = indicies[i+2]; + + LitVertex& lit_vertex0 = vertices[index0]; + LitVertex& lit_vertex1 = vertices[index1]; + LitVertex& lit_vertex2 = vertices[index2]; + + glm::vec3 pos0 = lit_vertex0.position; + glm::vec3 pos1 = lit_vertex1.position; + glm::vec3 pos2 = lit_vertex2.position; + + // Edges of the triangle : postion delta + glm::vec3 delta_pos1 = pos1 - pos0; + glm::vec3 delta_pos2 = pos2 - pos0; + + // UV delta + glm::vec2 delta_uv1 = lit_vertex1.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); + 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 718e23a..89de207 100644 --- a/src/gfx/model.cpp +++ b/src/gfx/model.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -27,13 +28,18 @@ 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; // 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) { std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl; @@ -63,7 +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 indices; + std::vector indicies; for (unsigned int i = 0; i < mesh->mNumVertices; i++) { LitVertex vertex; @@ -93,7 +99,7 @@ namespace simpleengine::gfx { aiFace face = mesh->mFaces[i]; for (int j = 0; j < face.mNumIndices; j++) { - indices.push_back(face.mIndices[j]); + indicies.push_back(face.mIndices[j]); } } @@ -121,8 +127,13 @@ namespace simpleengine::gfx { // Load normals texture maps loading_type = aiTextureType_NORMALS; - std::vector> normal_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_NO_COLOR); - if (!normal_maps.empty()) textures.emplace(loading_type, normal_maps); + std::vector> normal_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_RGB); + if (!normal_maps.empty()) { + textures.emplace(loading_type, normal_maps); + + // Force calculation of tangent space. + model_processing_flags |= MdlProcFlag_CALCULATE_TANGENT_SPACE; + } // TODO Handle other types of texture maps @@ -156,7 +167,7 @@ namespace simpleengine::gfx { } } - Mesh se_mesh(vertices, indices, mat); + Mesh se_mesh(vertices, indicies, mat); if (!mesh->HasNormals()) { se_mesh.calculate_normals(); @@ -222,4 +233,50 @@ namespace simpleengine::gfx { } } } + + void Model::calculate_tangents() { + for (auto& mesh : meshes) { + // TODO: Find a way to check if normals and UVs are set before calculating tangents + mesh.calculate_tangents(); + } + } + + /* std::vector> calculate_tangent_space( + std::vector vertices, std::vector indices) { + + std::vector> tangents; + tangents.resize(vertices.size()); + + for (int i = 0; i < indices.size(); i += 3) { + int index0 = indices[i]; + int index1 = indices[i+1]; + int index2 = indices[i+2]; + + LitVertex& lit_vertex0 = vertices[index0]; + LitVertex& lit_vertex1 = vertices[index1]; + LitVertex& lit_vertex2 = vertices[index2]; + + glm::vec3 pos0 = lit_vertex0.position; + glm::vec3 pos1 = lit_vertex1.position; + glm::vec3 pos2 = lit_vertex2.position; + + // Edges of the triangle : postion delta + glm::vec3 delta_pos1 = pos1 - pos0; + glm::vec3 delta_pos2 = pos2 - pos0; + + // UV delta + glm::vec2 delta_uv1 = lit_vertex1.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); + 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[0] = {tangent, bitangent}; + tangents[1] = {tangent, bitangent}; + tangents[2] = {tangent, bitangent}; + } + + return tangents; + } */ } // namespace simpleengine::gfx \ No newline at end of file diff --git a/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index 6377cfa..9a770b6 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -5,6 +5,7 @@ #include "ecs/component/mesh_component.h" #include "ecs/component/model_component.h" +#include "vector.h" #include #include @@ -60,8 +61,14 @@ namespace simpleengine::gfx { vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal), false); vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord), false); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); + 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(); rendering_mesh.are_buffers_created = true; @@ -125,6 +132,21 @@ namespace simpleengine::gfx { } else { shader.set_uniform_int("u_material.has_specular_map", 0, false); } + + // Apply the normal map if it exists + auto normal_maps = material->textures.find(aiTextureType_NORMALS); + if (normal_maps != material->textures.end()) { + auto normal = normal_maps->second.front(); + + //shader.set_uniform_int("u_material.has_normal_map", 1, false); + shader.set_uniform_int("u_material.normal_map", 2, false); + + glActiveTexture(GL_TEXTURE2); + normal->bind(); + } else { + //shader.set_uniform_int("u_material.has_normal_map", 0, false); + std::cout << "No normal map for model!" << std::endl; + } } mesh.vao.bind(); From 9a3240b25fda25e8fc49e1d594e6f0583977d332 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Thu, 29 Sep 2022 19:24:32 -0400 Subject: [PATCH 6/9] Don't output tangents and bitangents to fragement shader --- resources/shaders/core/3d/fragment_core.glsl | 5 ----- resources/shaders/core/3d/vertex_core.glsl | 6 ------ 2 files changed, 11 deletions(-) diff --git a/resources/shaders/core/3d/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl index c025137..18ab10d 100644 --- a/resources/shaders/core/3d/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -14,9 +14,6 @@ in vec3 vs_frag_pos; in mat3 vs_tbn; -in vec3 vs_tangent; -in vec3 vs_bitangent; - const int SAMP_DIFFUSE = 0; const int SAMP_SPECULAR = 1; @@ -49,8 +46,6 @@ void main() { fs_color = vec4(lighting, 1.f) * texture(u_material.diffuse, vs_texcoord); - //fs_color = vec4(vs_tangent, 1.f); - //fs_color = vec4(vs_bitangent, 1.f); } vec3 calculate_lighting() { diff --git a/resources/shaders/core/3d/vertex_core.glsl b/resources/shaders/core/3d/vertex_core.glsl index 5dbace3..984b2d1 100644 --- a/resources/shaders/core/3d/vertex_core.glsl +++ b/resources/shaders/core/3d/vertex_core.glsl @@ -22,9 +22,6 @@ out vec3 vs_frag_pos; out mat3 vs_tbn; -out vec3 vs_tangent; -out vec3 vs_bitangent; - uniform mat4 u_transform_matrix; uniform mat4 u_view_matrix; uniform mat4 u_projection_matrix; @@ -55,7 +52,4 @@ void main() { 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); - - vs_tangent = vertex_tangent; - vs_bitangent = vertex_bitangent; } \ No newline at end of file From 366ab195448d9bae611f99c3f1b6e4660ad97e27 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Fri, 30 Sep 2022 17:01:14 -0400 Subject: [PATCH 7/9] Make normal maps optional --- examples/dev_testing/src/main.cpp | 2 +- resources/shaders/core/3d/fragment_core.glsl | 16 ++++++++++------ src/gfx/renderer.cpp | 5 ++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/dev_testing/src/main.cpp b/examples/dev_testing/src/main.cpp index ed4d271..0b11aa1 100644 --- a/examples/dev_testing/src/main.cpp +++ b/examples/dev_testing/src/main.cpp @@ -172,7 +172,7 @@ int main(int argc, char *argv[]) { // entity.add_component("examples/dev_testing/resources/viper/viper.obj"); // entity.add_component("examples/dev_testing/resources/halot/chief.fbx"); - //entity.add_component("examples/dev_testing/resources/planks/planks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE); + // entity.add_component("examples/dev_testing/resources/planks/planks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE); entity.add_component("examples/dev_testing/resources/bricks/bricks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE); // entity.add_component("examples/dev_testing/resources/scientist/scientist.fbx"); diff --git a/resources/shaders/core/3d/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl index 18ab10d..218f012 100644 --- a/resources/shaders/core/3d/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -24,6 +24,7 @@ struct Material { sampler2D specular_map; // TODO: Make Optional + bool has_normal_map; sampler2D normal_map; float ambient_strength; @@ -53,11 +54,14 @@ vec3 calculate_lighting() { //float ambient_strength = 0.1; vec3 ambient = u_material.ambient_strength * u_light_color; - // Apply the normal map to the lighting. - vec3 normal = vs_normal; - normal = texture(u_material.normal_map, vs_texcoord).rgb; - normal = normal * 2.0 - 1.0; - normal = normalize(vs_tbn * normal); + vec3 normal = vs_world_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); + } // Diffuse vec3 norm = normalize(normal); @@ -72,7 +76,7 @@ vec3 calculate_lighting() { 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; - // Check if the specular map is set before trying to set it + // 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/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index 9a770b6..e336daa 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -138,14 +138,13 @@ namespace simpleengine::gfx { if (normal_maps != material->textures.end()) { auto normal = normal_maps->second.front(); - //shader.set_uniform_int("u_material.has_normal_map", 1, false); + shader.set_uniform_int("u_material.has_normal_map", 1, false); shader.set_uniform_int("u_material.normal_map", 2, false); glActiveTexture(GL_TEXTURE2); normal->bind(); } else { - //shader.set_uniform_int("u_material.has_normal_map", 0, false); - std::cout << "No normal map for model!" << std::endl; + shader.set_uniform_int("u_material.has_normal_map", 0, false); } } From 19d116ef659f67b5de4ae519bf2976c056313a92 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sun, 2 Oct 2022 11:39:07 -0400 Subject: [PATCH 8/9] 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(); From 6944d0ac6d7ce170fa84c9ee380d72c9feaaef68 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Tue, 11 Oct 2022 23:16:52 -0400 Subject: [PATCH 9/9] Implement sorting blending --- CMakeLists.txt | 2 + cmrc | 2 +- examples/dev_testing/CMakeLists.txt | 16 +- .../resources/shaders/fragment_core.glsl | 46 ---- .../resources/shaders/vertex_core.glsl | 31 --- examples/dev_testing/src/main.cpp | 131 ++------- include/simpleengine/gfx/material.h | 10 +- include/simpleengine/gfx/model.h | 3 +- include/simpleengine/gfx/renderer.h | 36 ++- include/simpleengine/gfx/rendering_type.h | 8 + include/simpleengine/gfx/texture.h | 20 +- resources/shaders/core/3d/fragment_core.glsl | 7 +- src/game.cpp | 4 +- src/gfx/model.cpp | 21 +- src/gfx/renderer.cpp | 252 +++++++++++------- src/gfx/texture.cpp | 77 +++--- src/scene.cpp | 14 +- 17 files changed, 306 insertions(+), 374 deletions(-) delete mode 100644 examples/dev_testing/resources/shaders/fragment_core.glsl delete mode 100644 examples/dev_testing/resources/shaders/vertex_core.glsl create mode 100644 include/simpleengine/gfx/rendering_type.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 500cdae..82bb540 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,8 @@ else() target_link_libraries(simpleengine PUBLIC assimp) endif() +# Link resources +target_link_libraries(simpleengine PUBLIC cmrc::base) target_link_libraries(simpleengine PRIVATE simpleengine_resources) # Include some dependencies' include directories diff --git a/cmrc b/cmrc index a64bea5..e386a62 160000 --- a/cmrc +++ b/cmrc @@ -1 +1 @@ -Subproject commit a64bea50c05594c8e7cf1f08e441bb9507742e2e +Subproject commit e386a629eb537d384811e598a3c96b9ca928f65e diff --git a/examples/dev_testing/CMakeLists.txt b/examples/dev_testing/CMakeLists.txt index 01a45e9..6253a89 100644 --- a/examples/dev_testing/CMakeLists.txt +++ b/examples/dev_testing/CMakeLists.txt @@ -9,17 +9,17 @@ target_sources(dev_testing PRIVATE ${source_list}) target_include_directories(dev_testing PUBLIC include) # Embed shaders -file(GLOB_RECURSE shaders_list resources/shaders/*.glsl) -cmrc_add_resource_library( - resource_shaders - WHENCE resources/shaders - PREFIX shaders - ${shaders_list} -) +#file(GLOB_RECURSE shaders_list resources/shaders/*.glsl) +#cmrc_add_resource_library( +# resource_shaders +# WHENCE resources/shaders +# PREFIX shaders +# ${shaders_list} +#) # Link simpleengine target_link_libraries(dev_testing PUBLIC simpleengine) -target_link_libraries(dev_testing PRIVATE resource_shaders) +#target_link_libraries(dev_testing PRIVATE resource_shaders) # Set standard to C++20 set_target_properties(dev_testing PROPERTIES CXX_STANDARD 20 CXX_EXTENSIONS OFF) \ No newline at end of file diff --git a/examples/dev_testing/resources/shaders/fragment_core.glsl b/examples/dev_testing/resources/shaders/fragment_core.glsl deleted file mode 100644 index d5fe2e6..0000000 --- a/examples/dev_testing/resources/shaders/fragment_core.glsl +++ /dev/null @@ -1,46 +0,0 @@ -#version 440 - -in vec3 vs_position; -in mat4 vs_transform; -in vec2 vs_texcoord; -in vec3 vs_normal; -in vec3 vs_to_light; -in vec3 vs_to_camera; - -uniform bool texture_is_set; -uniform sampler2D vs_texture; -uniform vec3 light_color; -uniform float shine_damper; -uniform float reflectivity; - -out vec4 fs_color; - -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; - - // Specular lighting - // only do all this math is reflectivity is > 0 - 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; - } - - if (texture_is_set) { - //fs_color = vec4(0.5 * unit_normal + vec3(0.5), 1.f); // Visualize normals - fs_color = vec4(diffuse, 1.f) * texture(vs_texture, vs_texcoord) + vec4(final_specular, 1.f); - } else { - fs_color = vec4(diffuse, 1.f) + vec4(final_specular, 1.f); - } -} \ No newline at end of file diff --git a/examples/dev_testing/resources/shaders/vertex_core.glsl b/examples/dev_testing/resources/shaders/vertex_core.glsl deleted file mode 100644 index 42b9be3..0000000 --- a/examples/dev_testing/resources/shaders/vertex_core.glsl +++ /dev/null @@ -1,31 +0,0 @@ -#version 440 - -layout (location = 0) in vec3 vertex_position; -layout (location = 1) in vec2 vertex_texcoord; -layout (location = 2) in vec3 vertex_normal; - -out vec3 vs_position; -out vec2 vs_texcoord; -out mat4 vs_transform; -out vec3 vs_normal; -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; - -void main() { - vec4 world_pos = (transform_matrix * vec4(vertex_position, 1.f)); - - vs_position = world_pos.xyz; - vs_transform = transform_matrix; - vs_texcoord = vertex_texcoord; - - gl_Position = projection_matrix * 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; -} \ No newline at end of file diff --git a/examples/dev_testing/src/main.cpp b/examples/dev_testing/src/main.cpp index 901cb11..ed161eb 100644 --- a/examples/dev_testing/src/main.cpp +++ b/examples/dev_testing/src/main.cpp @@ -31,9 +31,6 @@ #include #include -#include -CMRC_DECLARE(resource_shaders); - namespace se = simpleengine; class FPSCounterEvent : public se::Event { @@ -61,141 +58,43 @@ public: } }; -std::string read_resource_shader(const std::string &path) { - auto fs = cmrc::resource_shaders::get_filesystem(); - cmrc::file vertex_file = fs.open(path); - - return std::string(vertex_file.begin()); -} - int main(int argc, char *argv[]) { se::Game game(640, 480, "SimpleEngine 3D OpenGL - Developer Testing", GLFW_OPENGL_CORE_PROFILE, 4, 4, false); - /* se::gfx::Texture wall_texture("resources/wall.jpg"); - se::gfx::Texture crate_texture("resources/container.jpg", true, true); */ - // Load core shaders from SimpleEngine resources se::gfx::shaders::Core3dShader core_shader; - auto white_texture = se::gfx::Texture::white_texture(); - // white_texture.shine_damper = 10; - // white_texture.reflectivity = 1; - /* auto dragon = std::make_shared(game.get_window(), core_shader, white_texture, - "examples/dev_testing/resources/dragon.obj"); dragon->translate(0.f, -5.f, -15.f); game.add_event(dragon); */ - - /* auto cube = std::make_shared(game.get_window(), core_shader, white_texture, - "examples/dev_testing/resources/cube.obj"); cube->translate(0.f, -5.f, -15.f); game.add_event(cube); - - se::gfx::Texture grass("examples/dev_testing/resources/grass.png"); - auto terrain = std::make_shared(game.get_window(), core_shader, grass, 0, 0); - terrain->translate(0.f, -5.f, -15.f); - game.add_event(terrain); */ - - /* se::gfx::Texture stall_texture("examples/dev_testing/resources/stallTextureb.png"); - auto stall = std::make_shared(game.get_window(), core_shader, stall_texture, - "examples/dev_testing/resources/stall.obj"); stall->translate(10.f, -5.f, 0.f); stall->rotate_y(90.f); - game.add_event(stall); */ - - /* std::vector square_vertices = { - { se::Vectorf(0.5f, 0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f) }, // top right - { se::Vectorf(0.5f, -0.5f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, // bottom right - { se::Vectorf(-0.5f, -0.5f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.5f, 1.0f) }, // bottom left - { se::Vectorf(-0.5f, 0.5f, -1.f), glm::vec3(.5f, 0.5f, 0.f), glm::vec2(0.5f, 1.0f) }, // top left - }; - - std::vector indicies = { - 0, 1, 3, - 1, 2, 3 - }; - - auto square = std::make_shared(game.get_window(), core_shader, square_vertices, indicies); - square->translate(1.25f, 0.f, -1.f); - //square->rotate_y(90.f); - //square->scale(.75f); - game.add_event(square); */ - - /* se::gfx::Texture white_texture("examples/dev_testing/resources/white_texture.png"); - auto cube = std::make_shared(game.get_window(), core_shader, white_texture, - "examples/dev_testing/resources/cube.obj"); cube->translate(-1.25f, 0.f, -1.f); game.add_event(cube); */ - - /* std::vector tri_vertices = { - { se::Vectorf(-0.5f, -0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f) }, // top right - { se::Vectorf(0.5f, -0.5f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, // bottom right - { se::Vectorf(0.f, 0.5f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.5f, 1.0f) }, // bottom left - }; - - auto tri = std::make_shared(game.get_window(), core_shader, tri_vertices); - tri->translate(-1.25f, 0.f, -1.f); - tri->scale(.75f); - game.add_event(tri); */ - - std::vector cube_vertices = { - {se::Vectorf(-1.f, -1.f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f)}, - {se::Vectorf(1.f, -1.f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f)}, - {se::Vectorf(1.f, 1.f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 0.f)}, - {se::Vectorf(-1.f, 1.f, -1.f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 0.f)}, - {se::Vectorf(-1, -1, -1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 0.f)}, - - {se::Vectorf(-1, -1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 1.f)}, - {se::Vectorf(1, -1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 1.f)}, - {se::Vectorf(1, 1, 1), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 1.f)}, - {se::Vectorf(-1, 1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 1.f)}, - {se::Vectorf(-1, -1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 1.f)}, - - {se::Vectorf(-1, 1, -1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, -1.f)}, - {se::Vectorf(1, 1, -1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, -1.f)}, - - {se::Vectorf(-1, 1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 2.f)}, - {se::Vectorf(1, 1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 2.f)}, - }; - - std::vector cube_indicies = {0, 1, 5, 5, 1, 6, 1, 2, 6, 6, 2, 7, 2, 3, 7, 7, 3, 8, - 3, 4, 8, 8, 4, 9, 10, 11, 0, 0, 11, 1, 5, 6, 12, 12, 6, 13}; + auto camera = std::make_shared(game.get_window(), core_shader, 70, glm::vec3(0, 0, 0)); + game.add_event(camera); // Create a renderer - auto renderer = std::make_shared(game.get_window(), core_shader); + auto renderer = std::make_shared(game.get_window(), core_shader, camera); + renderer->initialize(); game.add_renderable(renderer); // Create a Scene and give it the renderer auto scene = std::make_shared(renderer); game.add_event(scene); + se::ecs::Entity other_e = scene->create_entity(); + other_e.add_component("examples/dev_testing/resources/transparent_window.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE | simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_TRANSPARENT); + auto &other_transform = other_e.add_component(); + other_transform.translate(5.f, 0.5f, 1.f); + // Create an Entity in the Scene and add components to it. se::ecs::Entity entity = scene->create_entity(); - // entity.add_component("examples/dev_testing/resources/dragon.obj"); - // entity.add_component("examples/dev_testing/resources/stall.obj"); - // Backpack model required vertically flipped texture coords. - /* auto& model_comp = - entity.add_component("examples/dev_testing/resources/backpack/backpack.obj"); - model_comp.model.vertically_flip_tex_coords(); */ - - // entity.add_component("examples/dev_testing/resources/viper/viper.obj"); - // entity.add_component("examples/dev_testing/resources/halot/chief.fbx"); // entity.add_component("examples/dev_testing/resources/planks/planks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE); - entity.add_component("examples/dev_testing/resources/bricks/bricks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE); + //entity.add_component("examples/dev_testing/resources/bricks/bricks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE); + entity.add_component("examples/dev_testing/resources/transparent_window.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE | simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_TRANSPARENT); - // entity.add_component("examples/dev_testing/resources/scientist/scientist.fbx"); - // entity.add_component("examples/dev_testing/resources/paradigm/paradigm.fbx"); - // entity.add_component(); auto &transform_comp = entity.add_component(); 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); - // transform_comp.rotate_x(-90.f); - // Create the entity and add the model component to it. - /* auto entity = std::make_shared(); - entity->add_component(cube_vertices, cube_indicies, white_material, true); - entity->translate(3.5f, 0.f, 0.f); */ - - /* auto entity = std::make_shared(); - entity->add_component("examples/dev_testing/resources/dragon.obj"); - entity->translate(12.f, -4.f, 0.f); */ - - auto camera = std::make_shared(game.get_window(), core_shader, 70, glm::vec3(0, 0, 0)); - game.add_event(camera); + se::ecs::Entity brick_e = scene->create_entity(); + brick_e.add_component("examples/dev_testing/resources/bricks/bricks.fbx", simpleengine::gfx::ModelProcessingFlags::MdlProcFlag_CALCULATE_TANGENT_SPACE); + auto &brick_transf = brick_e.add_component(); + brick_transf.translate(6.f, -0.5f, 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); diff --git a/include/simpleengine/gfx/material.h b/include/simpleengine/gfx/material.h index 50077d7..1acd12b 100644 --- a/include/simpleengine/gfx/material.h +++ b/include/simpleengine/gfx/material.h @@ -1,5 +1,6 @@ #pragma once +#include "rendering_type.h" #include "texture.h" #include @@ -10,6 +11,9 @@ namespace simpleengine::gfx { class Material { public: + RenderingType rendering_type; + + // TODO: Only one of each texture type. std::unordered_map>> textures; float ambient_strength; @@ -32,9 +36,9 @@ namespace simpleengine::gfx { */ float shine_factor; - 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) { + Material(std::unordered_map>> textures, RenderingType rendering_type, float shine = 1.f, + float specular_scalar = 1.f, float ambient_scalar = 1.f, float diffuse_scalar = 1.f) : textures(textures), rendering_type(rendering_type), + ambient_strength(ambient_scalar), diffuse_strength(diffuse_scalar), specular_strength(specular_scalar), shine_factor(shine) { } }; diff --git a/include/simpleengine/gfx/model.h b/include/simpleengine/gfx/model.h index 4aa8a31..4b3c899 100644 --- a/include/simpleengine/gfx/model.h +++ b/include/simpleengine/gfx/model.h @@ -16,6 +16,7 @@ namespace simpleengine::gfx { MdlProcFlag_FLIP_TEX_COORDS_VERTICALLY = 0b00000001, MdlProcFlag_FLIP_TEX_COORDS_HORIZONTALLY = 0b00000010, MdlProcFlag_CALCULATE_TANGENT_SPACE = 0b00000100, + MdlProcFlag_TRANSPARENT = 0b00001000, }; /** @@ -40,7 +41,7 @@ namespace simpleengine::gfx { gfx::Mesh process_mesh(std::unordered_map>>& processed_textures, aiMesh* mesh, const aiScene* scene); std::unordered_map> load_all_textures(aiMaterial* material); - std::vector> load_material_texture(std::unordered_map>>& processed_textures, aiMaterial* material, aiTextureType type, TextureFlags texture_color); + std::vector> load_material_texture(std::unordered_map>>& processed_textures, aiMaterial* material, aiTextureType type); protected: void post_process(); public: diff --git a/include/simpleengine/gfx/renderer.h b/include/simpleengine/gfx/renderer.h index 3cb5cce..684e7b7 100644 --- a/include/simpleengine/gfx/renderer.h +++ b/include/simpleengine/gfx/renderer.h @@ -1,36 +1,45 @@ #pragma once +#include "../camera.h" #include "shader.h" -#include "simpleengine/gfx/mesh.h" +#include "../renderable.h" +#include "rendering_type.h" #include #include #include +#include namespace simpleengine::gfx { + class Mesh; + class RenderingJob { public: - gfx::Mesh& rendering_mesh; + RenderingType rendering_type; + gfx::Mesh* rendering_mesh; glm::mat4 transform_mat; - RenderingJob(gfx::Mesh& mesh, glm::mat4 position) : rendering_mesh(mesh), transform_mat(position) { - - } + RenderingJob(RenderingType rendering_type, gfx::Mesh& mesh, glm::mat4 position); }; class Renderer : public simpleengine::Renderable { private: GLFWwindow* window; + protected: public: + std::queue transparent_render_queue; + std::queue other_render_queue; - std::queue rendering_queue; gfx::Shader shader; + std::shared_ptr camera; - Renderer(GLFWwindow* window, gfx::Shader shader); - Renderer(GLFWwindow* window, GLuint shader_program); + Renderer(GLFWwindow* window, gfx::Shader shader, std::shared_ptr camera); + Renderer(GLFWwindow* window, GLuint shader_program, std::shared_ptr camera); void enable_debug(); + virtual void sort_jobs(); + virtual void queue_job(RenderingType rendering_type, gfx::Mesh& mesh, glm::mat4 position); virtual void queue_job(RenderingJob job); virtual void create_job_buffers(RenderingJob& job); @@ -40,5 +49,16 @@ namespace simpleengine::gfx { virtual void update(const float& delta_time) override; virtual void render() override; + + /** + * @brief Renders a single job. + * + * @param job The job that will be rendered. + * @return true if the job was rendered successfully. + * @return false if there was an error when trying to render the job. + */ + virtual bool render_job(const RenderingJob& job); + virtual void render_job_queue(std::queue& queue); + virtual void render_job_queue(std::map>& queue); }; } \ No newline at end of file diff --git a/include/simpleengine/gfx/rendering_type.h b/include/simpleengine/gfx/rendering_type.h new file mode 100644 index 0000000..d6c66dc --- /dev/null +++ b/include/simpleengine/gfx/rendering_type.h @@ -0,0 +1,8 @@ +#pragma once + +namespace simpleengine::gfx { + enum RenderingType { + RendType_OPAQUE = 0, + RendType_TRANSPARENT = 1, + }; +} \ No newline at end of file diff --git a/include/simpleengine/gfx/texture.h b/include/simpleengine/gfx/texture.h index 32bffab..69c492e 100644 --- a/include/simpleengine/gfx/texture.h +++ b/include/simpleengine/gfx/texture.h @@ -23,39 +23,29 @@ namespace simpleengine::gfx { TexFlags_FLIP_VERTICALLY = 0b00000010, TexFlags_FLIP_HORIZONTALLY = 0b00000100, TexFlags_MIPMAP = 0b00001000, - TexFlags_NO_COLOR = 0b00010000, + /* TexFlags_NO_COLOR = 0b00010000, TexFlags_RGB = 0b00100000, - TexFlags_RGBA = 0b01000000, + TexFlags_RGBA = 0b01000000, */ }; class Texture { private: - unsigned char* img_data; // TODO Free this if its not used anymore + //unsigned char* img_data; // TODO Free this if its not used anymore unsigned int texture_id; unsigned int image_type_gl; Texture() = default; public: - /** - * @brief The default Texture flags not including the color. - * - * The default flags are `TexFlags_IMG_2D | TexFlags_MIPMAP` - * - * @see simpleengine::gfx::Texture::default_flags - * - */ - static constexpr int default_flags_no_color = TexFlags_IMG_2D | TexFlags_MIPMAP; - /** * @brief The default Texture flags including the color. * - * The default flags are `TexFlags_IMG_2D | TexFlags_MIPMAP | TexFlags_RGBA` + * The default flags are `TexFlags_IMG_2D | TexFlags_MIPMAP` * * @see simpleengine::gfx::Texture::default_flags_no_color * */ - static constexpr int default_flags = default_flags_no_color | TexFlags_RGBA; + static constexpr int default_flags = TexFlags_IMG_2D | TexFlags_MIPMAP; int height; int width; diff --git a/resources/shaders/core/3d/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl index 9801a5f..0751d1c 100644 --- a/resources/shaders/core/3d/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -47,8 +47,13 @@ out vec4 fs_color; vec3 calculate_lighting(); void main() { - vec3 lighting = calculate_lighting(); + // Skip completely transparent fragments. + /* vec4 diffuse = texture(u_material.diffuse, vs_texcoord); + if (diffuse.a < 0.1) { + discard; + } */ + vec3 lighting = calculate_lighting(); fs_color = vec4(lighting, 1.f) * texture(u_material.diffuse, vs_texcoord); } diff --git a/src/game.cpp b/src/game.cpp index 9d603e9..dc7d5ac 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -48,9 +48,7 @@ simpleengine::Game::Game(int w, int h, const std::string& window_name, const int } void simpleengine::Game::enable_default_gl_options() const { - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); + //glFrontFace(GL_CW); update_enabled_vsync(); diff --git a/src/gfx/model.cpp b/src/gfx/model.cpp index 8fd542c..956ea1d 100644 --- a/src/gfx/model.cpp +++ b/src/gfx/model.cpp @@ -1,5 +1,6 @@ #include "gfx/model.h" #include "gfx/material.h" +#include "gfx/rendering_type.h" #include "gfx/texture.h" #include "vector.h" @@ -107,11 +108,17 @@ namespace simpleengine::gfx { } } + // Get the rendering type + RenderingType rendering_type = RenderingType::RendType_OPAQUE; + if (model_processing_flags & ModelProcessingFlags::MdlProcFlag_TRANSPARENT) { + rendering_type = RenderingType::RendType_TRANSPARENT; + } + // Create a default material and white texture. 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); + gfx::Material mat(default_textures, rendering_type); if (mesh->mMaterialIndex >= 0) { std::cout << "TODO: Process model materials!" << std::endl; @@ -121,17 +128,17 @@ namespace simpleengine::gfx { // Load Diffuse texture maps aiTextureType loading_type = aiTextureType_DIFFUSE; - std::vector> diffuse_maps = load_material_texture(processed_textures, material, loading_type, TextureFlags::TexFlags_RGBA); + 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, TextureFlags::TexFlags_NO_COLOR); + 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, TextureFlags::TexFlags_RGB); + std::vector> normal_maps = load_material_texture(processed_textures, material, loading_type); if (!normal_maps.empty()) { textures.emplace(loading_type, normal_maps); @@ -143,7 +150,7 @@ namespace simpleengine::gfx { if (!textures.empty()) { // TODO: Find a way to let the user set the scalars. - mat = Material(textures); + mat = Material(textures, rendering_type); // Add `textures` into the `processed_textures` list. for (const auto& pair : textures) { @@ -189,7 +196,7 @@ namespace simpleengine::gfx { return {}; } - std::vector> Model::load_material_texture(std::unordered_map>>& processed_textures, aiMaterial* material, aiTextureType type, TextureFlags texture_color) { + std::vector> Model::load_material_texture(std::unordered_map>>& processed_textures, aiMaterial* material, aiTextureType type) { std::vector> textures; for (int i = 0; i < material->GetTextureCount(type); i++) { @@ -216,7 +223,7 @@ namespace simpleengine::gfx { ss << model_directory << "/" << texture_path; std::string full_path = ss.str(); - Texture texture(full_path.c_str(), type, Texture::default_flags_no_color | texture_color); + Texture texture(full_path.c_str(), type); texture.path = texture_path; textures.emplace_back(std::make_shared(texture)); diff --git a/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index 336568a..19879e9 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -9,25 +9,27 @@ #include #include +#include +#include +// TODO: Check if initialized before trying to do stuff namespace simpleengine::gfx { - void create_mesh_buffers(simpleengine::gfx::Mesh& mesh); + void create_mesh_buffers(simpleengine::gfx::Mesh &mesh); - Renderer::Renderer(GLFWwindow* window, gfx::Shader shader): window(window), shader(shader) { - - } + RenderingJob::RenderingJob(RenderingType rendering_type, gfx::Mesh &mesh, glm::mat4 position) + : rendering_type(rendering_type), rendering_mesh(&mesh), transform_mat(position) {} - Renderer::Renderer(GLFWwindow* window, GLuint shader_program): Renderer(window, - gfx::Shader(shader_program)) { + Renderer::Renderer(GLFWwindow *window, gfx::Shader shader, std::shared_ptr camera) + : window(window), shader(shader), camera(camera)/* , transparent_render_queue(CameraDistanceComparator(camera)) */ {} - } + Renderer::Renderer(GLFWwindow *window, GLuint shader_program, std::shared_ptr camera) + : Renderer(window, gfx::Shader(shader_program), camera) {} + + void debug_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, + const GLchar *message, const void *userParam) { - void debug_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, - GLsizei length, const GLchar* message, const void* userParam) { - fprintf(stderr, "%s type = 0x%x, severity = 0x%x, message = %s\n", - (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), - type, severity, message); + (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, severity, message); } void Renderer::enable_debug() { @@ -35,24 +37,49 @@ namespace simpleengine::gfx { glDebugMessageCallback(debug_message_callback, 0); } - void Renderer::queue_job(RenderingJob job) { - RenderingJob& emplace = rendering_queue.emplace(job); - create_job_buffers(emplace); + void Renderer::sort_jobs() { + // Sort transparents + + // std::sort() } - void Renderer::create_job_buffers(RenderingJob& job) { - Mesh& rendering_mesh = job.rendering_mesh; + void Renderer::queue_job(RenderingType rendering_type, gfx::Mesh &mesh, glm::mat4 position) { + RenderingJob job(rendering_type, mesh, position); - if (!rendering_mesh.are_buffers_created) { - gfx::VBO& vbo = rendering_mesh.vbo; - gfx::VBO& ebo = rendering_mesh.ebo; - gfx::VAO& vao = rendering_mesh.vao; + this->queue_job(job); + } + + void Renderer::queue_job(RenderingJob job) { + create_job_buffers(job); + + switch (job.rendering_type) { + case RenderingType::RendType_TRANSPARENT: { + /* glm::vec3 pos = job.transform_mat[3]; + float distance = glm::distance(pos, camera->position); */ + this->transparent_render_queue.emplace(job); + break; + } + default: + this->other_render_queue.emplace(job); + break; + } + + sort_jobs(); + } + + void Renderer::create_job_buffers(RenderingJob &job) { + Mesh *rendering_mesh = job.rendering_mesh; + + if (!rendering_mesh->are_buffers_created) { + gfx::VBO &vbo = rendering_mesh->vbo; + gfx::VBO &ebo = rendering_mesh->ebo; + gfx::VAO &vao = rendering_mesh->vao; vao.bind(); - vbo.buffer(rendering_mesh.vertices.data(), 0, sizeof(LitVertex) * rendering_mesh.vertices.size()); + vbo.buffer(rendering_mesh->vertices.data(), 0, sizeof(LitVertex) * rendering_mesh->vertices.size()); - if (!rendering_mesh.indicies.empty()) { - ebo.buffer(rendering_mesh.indicies.data(), 0, rendering_mesh.indicies.size() * sizeof(GLuint)); + if (!rendering_mesh->indicies.empty()) { + ebo.buffer(rendering_mesh->indicies.data(), 0, rendering_mesh->indicies.size() * sizeof(GLuint)); } // Enable VAO attributes @@ -61,23 +88,29 @@ namespace simpleengine::gfx { vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal), false); vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord), false); - 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->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); vbo.unbind(); vao.unbind(); - rendering_mesh.are_buffers_created = true; + rendering_mesh->are_buffers_created = true; std::cout << "Created render job buffers" << std::endl; } } - void Renderer::update(const float& delta_time) { - - } + void Renderer::update(const float &delta_time) {} void Renderer::initialize() { + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + std::cout << "Base Renderer initialized" << std::endl; } @@ -89,73 +122,112 @@ namespace simpleengine::gfx { } */ } - void Renderer::render() { + bool Renderer::render_job(const RenderingJob &job) { + Mesh *mesh = job.rendering_mesh; + + shader.set_uniform_matrix_4f("u_transform_matrix", job.transform_mat, false); + + std::optional &material = mesh->material; + + if (material.has_value()) { + 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); + + auto diffuse_maps = material->textures.find(aiTextureType_DIFFUSE); + auto diffuse_map = diffuse_maps->second.front(); + + shader.set_uniform_int("u_material.diffuse", 0, false); + + glActiveTexture(GL_TEXTURE0); + diffuse_map->bind(); + + // Apply the specular map if it exists + 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.has_specular_map", 1, false); + shader.set_uniform_int("u_material.specular_map", 1, false); + + glActiveTexture(GL_TEXTURE1); + spec->bind(); + } else { + shader.set_uniform_int("u_material.has_specular_map", 0, false); + } + + // Apply the normal map if it exists + auto normal_maps = material->textures.find(aiTextureType_NORMALS); + if (normal_maps != material->textures.end()) { + auto normal = normal_maps->second.front(); + + shader.set_uniform_int("u_material.has_normal_map", 1, false); + shader.set_uniform_int("u_material.normal_map", 2, false); + + glActiveTexture(GL_TEXTURE2); + normal->bind(); + } else { + shader.set_uniform_int("u_material.has_normal_map", 0, false); + } + } + + mesh->vao.bind(); + if (mesh->indicies.empty()) { + glDrawArrays(GL_TRIANGLES, 0, mesh->vertices.size()); + } else { + glDrawElements(GL_TRIANGLES, mesh->indicies.size(), GL_UNSIGNED_INT, 0); + } + + return true; + } + + void Renderer::render_job_queue(std::queue &rendering_queue) { shader.use(); - + while (!rendering_queue.empty()) { // Get the job from the queue, we'll remove it after we render. - RenderingJob& job = rendering_queue.front(); - Mesh& mesh = job.rendering_mesh; + RenderingJob &job = rendering_queue.front(); - shader.set_uniform_matrix_4f("u_transform_matrix", job.transform_mat, false); + bool res = this->render_job(job); - std::optional& material = mesh.material; - - if (material.has_value()) { - 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); - - auto diffuse_maps = material->textures.find(aiTextureType_DIFFUSE); - auto diffuse_map = diffuse_maps->second.front(); - - shader.set_uniform_int("u_material.diffuse", 0, false); - - glActiveTexture(GL_TEXTURE0); - diffuse_map->bind(); - - // Apply the specular map if it exists - 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.has_specular_map", 1, false); - shader.set_uniform_int("u_material.specular_map", 1, false); - - glActiveTexture(GL_TEXTURE1); - spec->bind(); - } else { - shader.set_uniform_int("u_material.has_specular_map", 0, false); - } - - // Apply the normal map if it exists - auto normal_maps = material->textures.find(aiTextureType_NORMALS); - if (normal_maps != material->textures.end()) { - auto normal = normal_maps->second.front(); - - shader.set_uniform_int("u_material.has_normal_map", 1, false); - shader.set_uniform_int("u_material.normal_map", 2, false); - - glActiveTexture(GL_TEXTURE2); - normal->bind(); - } else { - shader.set_uniform_int("u_material.has_normal_map", 0, false); - } + if (res) { + // Now we'll remove the job from the queue. + rendering_queue.pop(); } - - mesh.vao.bind(); - if (mesh.indicies.empty()) { - glDrawArrays(GL_TRIANGLES, 0, mesh.vertices.size()); - } else { - glDrawElements(GL_TRIANGLES, mesh.indicies.size(), GL_UNSIGNED_INT, 0); - } - - // Now we'll remove the job from the queue. - rendering_queue.pop(); } shader.unuse(); } -} \ No newline at end of file + + void Renderer::render_job_queue(std::map>& rendering_queue) { + shader.use(); + + // Render each job then clear the queue + for (const auto& it : rendering_queue) { + this->render_job(it.second); + } + rendering_queue.clear(); + + shader.unuse(); + } + + void Renderer::render() { + // Render other (opaque) objects first + this->render_job_queue(other_render_queue); + + // Render transparent objects + std::map> transparent_jobs; + while (!transparent_render_queue.empty()) { + RenderingJob& job = transparent_render_queue.front(); + + glm::vec3 pos = job.transform_mat[3]; + float distance = glm::distance(pos, camera->position); + transparent_jobs.emplace(distance, job); + + transparent_render_queue.pop(); + } + this->render_job_queue(transparent_jobs); + } +} // namespace simpleengine::gfx \ No newline at end of file diff --git a/src/gfx/texture.cpp b/src/gfx/texture.cpp index 4e2fc3d..257c5d0 100644 --- a/src/gfx/texture.cpp +++ b/src/gfx/texture.cpp @@ -10,24 +10,6 @@ namespace simpleengine::gfx { bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY; bool mipmap = flags & TextureFlags::TexFlags_MIPMAP; - // Get the color channel type for opengl, and get - // the channel count for loading the texture with stb_image - int gl_color_channels; - int channel_count; - if (flags & TexFlags_RGBA) { - channel_count = 4; - gl_color_channels = GL_RGBA; - } else if (flags & TexFlags_RGB) { - channel_count = 3; - gl_color_channels = GL_RGB; - } else if (flags & TexFlags_NO_COLOR) { - channel_count = 1; - gl_color_channels = GL_RED; - } else { - std::cerr << "Texture color flag is missing!! Specify TexFlags_RGBA" << std::endl; - throw std::runtime_error("Texture color flag is missing!! Specify TexFlags_RGBA"); - } - image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D; glGenTextures(1, &texture_id); @@ -42,7 +24,7 @@ namespace simpleengine::gfx { stbi_set_flip_vertically_on_load(flip_vertically); - img_data = stbi_load(path, &width, &height, &channels, channel_count); + unsigned char*img_data = stbi_load(path, &width, &height, &channels, 0); if(!img_data) { const char* failure = stbi_failure_reason(); std::cerr << "Failed to load texture! (" << failure << ")" << std::endl; @@ -50,13 +32,27 @@ namespace simpleengine::gfx { } std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl; - glTexImage2D(image_type_gl, 0, gl_color_channels, width, height, 0, gl_color_channels, GL_UNSIGNED_BYTE, img_data); + // Get the color type + int color_format = 0; + if (channels == 1) { + color_format = GL_RED; + } else if (channels == 3) { + color_format = GL_RGB; + } else if (channels == 4) { + color_format = GL_RGBA; + } else { + std::cerr << "Unknown texture color format with " << channels << " channels!" << std::endl; + throw std::runtime_error("Unknown texture color format!"); + } + + glTexImage2D(image_type_gl, 0, color_format, width, height, 0, color_format, GL_UNSIGNED_BYTE, img_data); if (mipmap) { glGenerateMipmap(image_type_gl); } stbi_set_flip_vertically_on_load(false); + stbi_image_free(img_data); unbind(); } @@ -66,24 +62,6 @@ namespace simpleengine::gfx { bool flip_vertically = flags & TextureFlags::TexFlags_FLIP_VERTICALLY; bool mipmap = flags & TextureFlags::TexFlags_MIPMAP; - // Get the color channel type for opengl, and get - // the channel count for loading the texture with stb_image - int gl_color_channels; - int channel_count; - if (flags & TexFlags_RGBA) { - channel_count = 4; - gl_color_channels = GL_RGBA; - } else if (flags & TexFlags_RGB) { - channel_count = 3; - gl_color_channels = GL_RGB; - } else if (flags & TexFlags_NO_COLOR) { - channel_count = 1; - gl_color_channels = GL_RED; - } else { - std::cerr << "Texture color flag is missing!! Specify TexFlags_RGBA" << std::endl; - throw std::runtime_error("Texture color flag is missing!! Specify TexFlags_RGBA"); - } - image_type_gl = img_2d ? GL_TEXTURE_2D : GL_TEXTURE_3D; glGenTextures(1, &texture_id); @@ -98,7 +76,7 @@ namespace simpleengine::gfx { stbi_set_flip_vertically_on_load(flip_vertically); - img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, channel_count); + unsigned char* img_data = stbi_load_from_memory(buffer, buffer_length, &width, &height, &channels, 0); if(!img_data) { const char* failure = stbi_failure_reason(); std::cerr << "Failed to load texture! (" << failure << ")" << std::endl; @@ -106,13 +84,27 @@ namespace simpleengine::gfx { } std::cout << "Loaded image with a width of " << width << "px, a height of " << height << "px and " << channels << " channels" << std::endl; - glTexImage2D(image_type_gl, 0, gl_color_channels, width, height, 0, gl_color_channels, GL_UNSIGNED_BYTE, img_data); + // Get the color type + int color_format = 0; + if (channels == 1) { + color_format = GL_RED; + } else if (channels == 3) { + color_format = GL_RGB; + } else if (channels == 4) { + color_format = GL_RGBA; + } else { + std::cerr << "Unknown texture color format with " << channels << " channels!" << std::endl; + throw std::runtime_error("Unknown texture color format!"); + } + + glTexImage2D(image_type_gl, 0, color_format, width, height, 0, color_format, GL_UNSIGNED_BYTE, img_data); if (mipmap) { glGenerateMipmap(image_type_gl); } stbi_set_flip_vertically_on_load(false); + stbi_image_free(img_data); unbind(); } @@ -138,7 +130,6 @@ namespace simpleengine::gfx { texture.height = height; texture.channels = 4; texture.type = aiTextureType::aiTextureType_DIFFUSE; - texture.img_data = data; glGenTextures(1, &texture.texture_id); texture.bind(); @@ -148,10 +139,12 @@ namespace simpleengine::gfx { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.img_data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); texture.unbind(); + free(data); + return texture; } diff --git a/src/scene.cpp b/src/scene.cpp index c2caeff..8a5e735 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -19,12 +19,22 @@ namespace simpleengine { // Is there a way these can be grouped? registry.view().each([this](const TransformComponent& transform, ModelComponent& model_component) { for (auto& mesh : model_component.model.meshes) { - renderer->queue_job(gfx::RenderingJob(mesh, transform.transform_matrix)); + auto rendering_type = gfx::RenderingType::RendType_OPAQUE; + if (mesh.material) { + rendering_type = mesh.material->rendering_type; + } + + renderer->queue_job(gfx::RenderingJob(rendering_type, mesh, transform.transform_matrix)); } }); registry.view().each([this](const TransformComponent& transform, MeshComponent& mesh_component) { - renderer->queue_job(gfx::RenderingJob(mesh_component.mesh, transform.transform_matrix)); + auto rendering_type = gfx::RenderingType::RendType_OPAQUE; + if (mesh_component.mesh.material) { + rendering_type = mesh_component.mesh.material->rendering_type; + } + + renderer->queue_job(gfx::RenderingJob(rendering_type, mesh_component.mesh, transform.transform_matrix)); }); registry.view().each([this, &delta_time](TransformComponent& transform, RotatingComponent& rotating) {