feat(render): add shadow pass for entity models

This commit is contained in:
2026-07-25 11:57:00 +08:00
parent 5951a5e81c
commit 2e3b4f4f0f
6 changed files with 56 additions and 24 deletions

View File

@@ -13,10 +13,13 @@ public:
void render_model(const std::string& name, const glm::vec3& pos, void render_model(const std::string& name, const glm::vec3& pos,
Camera& camera); Camera& camera);
void shadow_pass(const std::string& name, const glm::vec3& pos,
const glm::mat4& light_matrix, Camera& camera);
private: private:
Renderer& m_renderer; Renderer& m_renderer;
void render_node(const ModelNode& node, const glm::mat4& parent, void 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);
void render_mesh(const Mesh& mesh); void render_mesh(const Mesh& mesh, bool shadow);
}; };
} // namespace Cubed } // namespace Cubed

View File

@@ -82,10 +82,8 @@ public:
bool handle_event(const Event& e); bool handle_event(const Event& e);
void render_model(const std::string& name, const glm::vec3& pos,
Camera& camera);
ModelManager& model_manager(); ModelManager& model_manager();
ModelRender& model_renderer();
private: private:
TextureManager& m_texture_manager; TextureManager& m_texture_manager;

View File

@@ -133,6 +133,7 @@ private:
void render_underwater(ClientWorld& world); void render_underwater(ClientWorld& world);
void render_outline(ClientWorld& world); void render_outline(ClientWorld& world);
void render_entity(ClientWorld& world); void render_entity(ClientWorld& world);
void shadow_entity(ClientWorld& world, const glm::mat4& light_matrix);
void render_player(ClientWorld& world); void render_player(ClientWorld& world);
void render_normal_block(const glm::mat4& model_mat, void render_normal_block(const glm::mat4& model_mat,

View File

@@ -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); glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos);
auto& shader = m_renderer.get_shader("model_shader"); auto& shader = m_renderer.get_shader("model_shader");
glm::mat4 view = camera.get_camera_lookat(); glm::mat4 view = camera.get_camera_lookat();
shader.use();
shader.set_loc("proj_matrix", m_renderer.p_mat()); 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, 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; 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) { for (auto& mesh : node.meshes) {
render_mesh(mesh); render_mesh(mesh, shadow);
} }
for (auto& child : node.children) { 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(); mesh.vao->bind();
if (mesh.texture) { if (mesh.texture) {
mesh.texture->bind(0); mesh.texture->bind(0);

View File

@@ -250,12 +250,6 @@ void Renderer::render_dev_panel(DevPanel& dev_panel) {
glEnable(GL_DEPTH_TEST); 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) { bool Renderer::handle_event(const Event& e) {
return std::visit(Overloaded{[](const MouseMoveEvent&) { return false; }, return std::visit(Overloaded{[](const MouseMoveEvent&) { return false; },
[](const MouseButtonEvent&) { 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 glm::mat4& Renderer::p_mat() const { return m_world_proj_matrix; }
const std::vector<VertexArray>& Renderer::vao() const { return m_vao; } const std::vector<VertexArray>& Renderer::vao() const { return m_vao; }
ModelManager& Renderer::model_manager() { return m_model_manager; } ModelManager& Renderer::model_manager() { return m_model_manager; }
ModelRender& Renderer::model_renderer() { return m_model_renderer; }
} // namespace Cubed } // namespace Cubed

View File

@@ -45,6 +45,9 @@ void WorldRenderer::render(ClientWorld& world) {
day_night_calculation(world); day_night_calculation(world);
render_sky(world); render_sky(world);
if (m_shader_on) {
shadow_map_generate(world);
}
render_world(world); render_world(world);
render_outline(world); render_outline(world);
render_entity(world); render_entity(world);
@@ -229,10 +232,6 @@ void WorldRenderer::render_world(ClientWorld& world) {
glm::mat4 norm_mat = glm::transpose(glm::inverse(mv_mat)); glm::mat4 norm_mat = glm::transpose(glm::inverse(mv_mat));
if (m_shader_on) {
shadow_map_generate(world);
}
m_world_fbo->bind(); m_world_fbo->bind();
glCullFace(GL_BACK); glCullFace(GL_BACK);
@@ -293,11 +292,28 @@ void WorldRenderer::render_outline(ClientWorld& world) {
} }
void WorldRenderer::render_entity(ClientWorld& world) { void WorldRenderer::render_entity(ClientWorld& world) {
glEnable(GL_DEPTH_TEST);
auto& registry = world.get_registry(); auto& registry = world.get_registry();
auto view = registry.view<Transform, Model>(); auto view = registry.view<Transform, Model>();
auto& shader = m_renderer.get_shader("model_shader");
shader.use();
for (auto entity : view) { for (auto entity : view) {
auto [transform, model] = view.get<Transform, Model>(entity); auto [transform, model] = view.get<Transform, Model>(entity);
m_renderer.render_model(model.name, transform.pos, 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<Transform, Model>();
auto& shader = m_renderer.get_shader("depth_model");
shader.use();
for (auto entity : view) {
auto [transform, model] = view.get<Transform, Model>(entity);
m_renderer.model_renderer().shadow_pass(model.name, transform.pos,
light_matrix,
world.world_scene().camera()); world.world_scene().camera());
} }
} }
@@ -404,6 +420,9 @@ void WorldRenderer::shadow_map_generate(ClientWorld& world) {
snapshot->normal_discard_vertices_count); snapshot->normal_discard_vertices_count);
} }
} }
shadow_entity(world, light_space_matrix);
// player // player
auto& player_shadow = m_renderer.get_shader("depth_model"); auto& player_shadow = m_renderer.get_shader("depth_model");
m_player_renderer.shadow_render(player_shadow, light_space_matrix, world); m_player_renderer.shadow_render(player_shadow, light_space_matrix, world);