From 2e3b4f4f0f920b0be6aec6c17ea073efb875d798 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sat, 25 Jul 2026 11:57:00 +0800 Subject: [PATCH] feat(render): add shadow pass for entity models --- include/Cubed/render/model_renderer.hpp | 7 ++++-- include/Cubed/render/renderer.hpp | 4 +--- include/Cubed/render/world_renderer.hpp | 1 + src/render/model_renderer.cpp | 30 ++++++++++++++++++------ src/render/renderer.cpp | 7 +----- src/render/world_renderer.cpp | 31 ++++++++++++++++++++----- 6 files changed, 56 insertions(+), 24 deletions(-) diff --git a/include/Cubed/render/model_renderer.hpp b/include/Cubed/render/model_renderer.hpp index 64df2a4..7200d5a 100644 --- a/include/Cubed/render/model_renderer.hpp +++ b/include/Cubed/render/model_renderer.hpp @@ -13,10 +13,13 @@ public: void render_model(const std::string& name, const glm::vec3& pos, Camera& camera); + void shadow_pass(const std::string& name, const glm::vec3& pos, + const glm::mat4& light_matrix, Camera& camera); + private: Renderer& m_renderer; void render_node(const ModelNode& node, const glm::mat4& parent, - const glm::mat4& view, const Shader& shader); - void render_mesh(const Mesh& mesh); + const glm::mat4& view, const Shader& shader, bool shadow); + void render_mesh(const Mesh& mesh, bool shadow); }; } // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/render/renderer.hpp b/include/Cubed/render/renderer.hpp index 15a57d1..df772f1 100644 --- a/include/Cubed/render/renderer.hpp +++ b/include/Cubed/render/renderer.hpp @@ -82,10 +82,8 @@ public: bool handle_event(const Event& e); - void render_model(const std::string& name, const glm::vec3& pos, - Camera& camera); - ModelManager& model_manager(); + ModelRender& model_renderer(); private: TextureManager& m_texture_manager; diff --git a/include/Cubed/render/world_renderer.hpp b/include/Cubed/render/world_renderer.hpp index 2867392..5241a6d 100644 --- a/include/Cubed/render/world_renderer.hpp +++ b/include/Cubed/render/world_renderer.hpp @@ -133,6 +133,7 @@ private: void render_underwater(ClientWorld& world); void render_outline(ClientWorld& world); void render_entity(ClientWorld& world); + void shadow_entity(ClientWorld& world, const glm::mat4& light_matrix); void render_player(ClientWorld& world); void render_normal_block(const glm::mat4& model_mat, diff --git a/src/render/model_renderer.cpp b/src/render/model_renderer.cpp index c6b2ba3..852cdc6 100644 --- a/src/render/model_renderer.cpp +++ b/src/render/model_renderer.cpp @@ -13,27 +13,43 @@ void ModelRender::render_model(const std::string& name, const glm::vec3& pos, glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos); auto& shader = m_renderer.get_shader("model_shader"); glm::mat4 view = camera.get_camera_lookat(); - shader.use(); shader.set_loc("proj_matrix", m_renderer.p_mat()); - render_node(root, transform, view, shader); + render_node(root, transform, view, shader, false); +} + +void ModelRender::shadow_pass(const std::string& name, const glm::vec3& pos, + const glm::mat4& light_matrix, Camera& camera) { + auto& model_manager = m_renderer.model_manager(); + auto& root = model_manager.get_model(name); + glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos); + auto& shader = m_renderer.get_shader("depth_model"); + glm::mat4 view = camera.get_camera_lookat(); + + shader.set_loc("lightSpaceMatrix", light_matrix); + render_node(root, transform, view, shader, true); } void ModelRender::render_node(const ModelNode& node, const glm::mat4& parent, - const glm::mat4& view, const Shader& shader) { + const glm::mat4& view, const Shader& shader, + bool shadow) { glm::mat4 transform = parent * node.transform; + if (shadow) { + shader.set_loc("modelMatrix", transform); + } else { + shader.set_loc("mv_matrix", view * transform); + } - shader.set_loc("mv_matrix", view * transform); for (auto& mesh : node.meshes) { - render_mesh(mesh); + render_mesh(mesh, shadow); } for (auto& child : node.children) { - render_node(child, transform, view, shader); + render_node(child, transform, view, shader, shadow); } } -void ModelRender::render_mesh(const Mesh& mesh) { +void ModelRender::render_mesh(const Mesh& mesh, bool) { mesh.vao->bind(); if (mesh.texture) { mesh.texture->bind(0); diff --git a/src/render/renderer.cpp b/src/render/renderer.cpp index 80ffe37..494a5fa 100644 --- a/src/render/renderer.cpp +++ b/src/render/renderer.cpp @@ -250,12 +250,6 @@ void Renderer::render_dev_panel(DevPanel& dev_panel) { glEnable(GL_DEPTH_TEST); } -void Renderer::render_model(const std::string& name, const glm::vec3& pos, - Camera& camera) { - glEnable(GL_DEPTH_TEST); - m_model_renderer.render_model(name, pos, camera); -} - bool Renderer::handle_event(const Event& e) { return std::visit(Overloaded{[](const MouseMoveEvent&) { return false; }, [](const MouseButtonEvent&) { return false; }, @@ -348,4 +342,5 @@ float Renderer::frame_width() const { return m_frame_width; } const glm::mat4& Renderer::p_mat() const { return m_world_proj_matrix; } const std::vector& Renderer::vao() const { return m_vao; } ModelManager& Renderer::model_manager() { return m_model_manager; } +ModelRender& Renderer::model_renderer() { return m_model_renderer; } } // namespace Cubed \ No newline at end of file diff --git a/src/render/world_renderer.cpp b/src/render/world_renderer.cpp index b4e0da5..6db32f8 100644 --- a/src/render/world_renderer.cpp +++ b/src/render/world_renderer.cpp @@ -45,6 +45,9 @@ void WorldRenderer::render(ClientWorld& world) { day_night_calculation(world); render_sky(world); + if (m_shader_on) { + shadow_map_generate(world); + } render_world(world); render_outline(world); render_entity(world); @@ -229,10 +232,6 @@ void WorldRenderer::render_world(ClientWorld& world) { glm::mat4 norm_mat = glm::transpose(glm::inverse(mv_mat)); - if (m_shader_on) { - shadow_map_generate(world); - } - m_world_fbo->bind(); glCullFace(GL_BACK); @@ -293,12 +292,29 @@ void WorldRenderer::render_outline(ClientWorld& world) { } void WorldRenderer::render_entity(ClientWorld& world) { + glEnable(GL_DEPTH_TEST); auto& registry = world.get_registry(); auto view = registry.view(); + auto& shader = m_renderer.get_shader("model_shader"); + shader.use(); for (auto entity : view) { auto [transform, model] = view.get(entity); - m_renderer.render_model(model.name, transform.pos, - world.world_scene().camera()); + m_renderer.model_renderer().render_model(model.name, transform.pos, + world.world_scene().camera()); + } +} + +void WorldRenderer::shadow_entity(ClientWorld& world, + const glm::mat4& light_matrix) { + auto& registry = world.get_registry(); + auto view = registry.view(); + auto& shader = m_renderer.get_shader("depth_model"); + shader.use(); + for (auto entity : view) { + auto [transform, model] = view.get(entity); + m_renderer.model_renderer().shadow_pass(model.name, transform.pos, + light_matrix, + world.world_scene().camera()); } } @@ -404,6 +420,9 @@ void WorldRenderer::shadow_map_generate(ClientWorld& world) { snapshot->normal_discard_vertices_count); } } + + shadow_entity(world, light_space_matrix); + // player auto& player_shadow = m_renderer.get_shader("depth_model"); m_player_renderer.shadow_render(player_shadow, light_space_matrix, world);