From 915c5582c5c44becdf6db8f7e84d07f3e64ae27b Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 12 Jan 2023 05:26:21 +0800 Subject: [PATCH] Improve shadow map pass --- src/game/world.cpp | 4 +- src/render/passes/material-pass.cpp | 5 ++ src/render/passes/material-pass.hpp | 1 + src/render/passes/shadow-map-pass.cpp | 19 ++++---- src/scene/directional-light.cpp | 2 +- src/scene/directional-light.hpp | 70 +++++++++++++++------------ 6 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/game/world.cpp b/src/game/world.cpp index cc62594..283ef80 100644 --- a/src/game/world.cpp +++ b/src/game/world.cpp @@ -420,10 +420,10 @@ void create_sun(game::context& ctx) sun_light->set_color({0, 0, 0}); sun_light->set_shadow_caster(true); sun_light->set_shadow_framebuffer(ctx.shadow_map_framebuffer); - sun_light->set_shadow_bias(1.0f); + sun_light->set_shadow_bias(0.005f); sun_light->set_shadow_cascade_count(4); sun_light->set_shadow_cascade_coverage(0.1f); - sun_light->set_shadow_cascade_distribution(0.8f); + sun_light->set_shadow_cascade_distribution(0.85f); sun_light->update_tweens(); // Create sky ambient light scene object diff --git a/src/render/passes/material-pass.cpp b/src/render/passes/material-pass.cpp index 9aff24c..f47252c 100644 --- a/src/render/passes/material-pass.cpp +++ b/src/render/passes/material-pass.cpp @@ -147,6 +147,7 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con unsigned int shadow_cascade_count = 0; const float* shadow_splits_directional = nullptr; const float4x4* shadow_matrices_directional = nullptr; + float shadow_bias_directional = 0.0f; // Collect lights const std::list* lights = ctx.collection->get_objects(scene::light::object_type_id); @@ -205,6 +206,7 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con { if (directional_light->get_shadow_framebuffer()) shadow_map_texture = directional_light->get_shadow_framebuffer()->get_depth_attachment(); + shadow_bias_directional = directional_light->get_shadow_bias(); shadow_cascade_count = directional_light->get_shadow_cascade_count(); shadow_splits_directional = directional_light->get_shadow_cascade_distances(); shadow_matrices_directional = directional_light->get_shadow_cascade_matrices(); @@ -469,6 +471,8 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con if (parameters->shadow_map_directional && shadow_map_texture) parameters->shadow_map_directional->upload(shadow_map_texture); + if (parameters->shadow_bias_directional) + parameters->shadow_bias_directional->upload(shadow_bias_directional); if (parameters->shadow_matrices_directional) parameters->shadow_matrices_directional->upload(0, shadow_matrices_directional, shadow_cascade_count); if (parameters->shadow_splits_directional) @@ -574,6 +578,7 @@ const material_pass::parameter_set* material_pass::load_parameter_set(const gl:: parameters->spot_light_attenuations = program->get_input("spot_light_attenuations"); parameters->spot_light_cutoffs = program->get_input("spot_light_cutoffs"); parameters->shadow_map_directional = program->get_input("shadow_map_directional"); + parameters->shadow_bias_directional = program->get_input("shadow_bias_directional"); parameters->shadow_splits_directional = program->get_input("shadow_splits_directional"); parameters->shadow_matrices_directional = program->get_input("shadow_matrices_directional"); parameters->skinning_palette = program->get_input("skinning_palette"); diff --git a/src/render/passes/material-pass.hpp b/src/render/passes/material-pass.hpp index 2601bf6..ba0f6b0 100644 --- a/src/render/passes/material-pass.hpp +++ b/src/render/passes/material-pass.hpp @@ -92,6 +92,7 @@ private: const gl::shader_input* spot_light_cutoffs; const gl::shader_input* shadow_map_directional; + const gl::shader_input* shadow_bias_directional; const gl::shader_input* shadow_splits_directional; const gl::shader_input* shadow_matrices_directional; diff --git a/src/render/passes/shadow-map-pass.cpp b/src/render/passes/shadow-map-pass.cpp index a6eaa6d..b3937e7 100644 --- a/src/render/passes/shadow-map-pass.cpp +++ b/src/render/passes/shadow-map-pass.cpp @@ -117,12 +117,14 @@ void shadow_map_pass::render_csm(const scene::directional_light& light, const re bool two_sided = false; // For half-z buffer - //glDepthRange(-1.0f, 1.0f); + glDepthRange(-1.0f, 1.0f); // Get camera const scene::camera& camera = *ctx.camera; - // Get distances to camera depth clipping planes + // Get tweened camera parameters + const float camera_fov = camera.get_fov_tween().interpolate(ctx.alpha); + const float camera_aspect_ratio = camera.get_aspect_ratio_tween().interpolate(ctx.alpha); const float camera_clip_near = camera.get_clip_near_tween().interpolate(ctx.alpha); const float camera_clip_far = camera.get_clip_far_tween().interpolate(ctx.alpha); @@ -170,9 +172,6 @@ void shadow_map_pass::render_csm(const scene::directional_light& light, const re float4x4 light_projection = math::ortho_half_z(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); float4x4 light_view_projection = light_projection * light_view; - // Get the camera's view matrix - float4x4 camera_view = camera.get_view_tween().interpolate(ctx.alpha); - float4x4 crop_matrix; float4x4 cropped_view_projection; float4x4 model_view_projection; @@ -191,10 +190,10 @@ void shadow_map_pass::render_csm(const scene::directional_light& light, const re // Calculate projection matrix for view camera subfrustum const float subfrustum_near = (i) ? cascade_distances[i - 1] : camera_clip_near; const float subfrustum_far = cascade_distances[i]; - float4x4 subfrustum_projection = math::perspective_half_z(camera.get_fov(), camera.get_aspect_ratio(), subfrustum_near, subfrustum_far); + float4x4 subfrustum_projection = math::perspective_half_z(camera_fov, camera_aspect_ratio, subfrustum_near, subfrustum_far); // Calculate view camera subfrustum - geom::view_frustum subfrustum(subfrustum_projection * camera_view); + geom::view_frustum subfrustum(subfrustum_projection * ctx.view); // Create AABB containing the view camera subfrustum corners const std::array& subfrustum_corners = subfrustum.get_corners(); @@ -219,9 +218,9 @@ void shadow_map_pass::render_csm(const scene::directional_light& light, const re //scale.z() = 2.0f / (cropping_bounds.max_point.z() - cropping_bounds.min_point.z()); // Quantize scale - float scale_quantizer = 64.0f; - scale.x() = 1.0f / std::ceil(1.0f / scale.x() * scale_quantizer) * scale_quantizer; - scale.y() = 1.0f / std::ceil(1.0f / scale.y() * scale_quantizer) * scale_quantizer; + // float scale_quantizer = 64.0f; + // scale.x() = 1.0f / std::ceil(1.0f / scale.x() * scale_quantizer) * scale_quantizer; + // scale.y() = 1.0f / std::ceil(1.0f / scale.y() * scale_quantizer) * scale_quantizer; // Calculate offset float3 offset; diff --git a/src/scene/directional-light.cpp b/src/scene/directional-light.cpp index 1697e06..1d8aa57 100644 --- a/src/scene/directional-light.cpp +++ b/src/scene/directional-light.cpp @@ -35,7 +35,7 @@ directional_light::directional_light(): direction(config::global_forward, interpolate_direction), shadow_caster(false), shadow_framebuffer(nullptr), - shadow_bias(1.0f), + shadow_bias(0.005f), shadow_cascade_count(4), shadow_cascade_coverage(1.0f), shadow_cascade_distribution(0.8f), diff --git a/src/scene/directional-light.hpp b/src/scene/directional-light.hpp index 9968b8f..5c02240 100644 --- a/src/scene/directional-light.hpp +++ b/src/scene/directional-light.hpp @@ -36,6 +36,18 @@ public: /// Creates a directional light. directional_light(); + /// Returns light_type::directional. + virtual light_type get_light_type() const; + + /// Returns the normalized direction vector of the light. + const float3& get_direction() const; + + /// @copydoc object_base::update_tweens(); + virtual void update_tweens(); + + /// @name Shadow + /// @{ + /** * Enables or disables shadow casting. * @@ -78,33 +90,6 @@ public: */ void set_shadow_cascade_distribution(float weight) noexcept; - /** - * Sets the light texture, also known as a gobo, cucoloris, or cookie. - * - * @param texture Light texture. - */ - void set_light_texture(const gl::texture_2d* texture); - - /** - * Sets the opacity of the light texture. - * - * @param opacity Light texture opacity, on `[0, 1]`. - */ - void set_light_texture_opacity(float opacity); - - /** - * Sets the scale of the light texture. - * - * @param scale Scale of the light texture. - */ - void set_light_texture_scale(const float2& scale); - - /// Returns light_type::directional. - virtual light_type get_light_type() const; - - /// Returns the normalized direction vector of the light. - const float3& get_direction() const; - /// Returns `true` if the light casts shadows, `false` otherwise. bool is_shadow_caster() const noexcept; @@ -129,6 +114,32 @@ public: /// Returns the array of world-space to cascade texture-space transformation matrices. float4x4* get_shadow_cascade_matrices() const noexcept; + /// @} + + /// @name Light texture + /// @{ + + /** + * Sets the light texture, also known as a gobo, cucoloris, or cookie. + * + * @param texture Light texture. + */ + void set_light_texture(const gl::texture_2d* texture); + + /** + * Sets the opacity of the light texture. + * + * @param opacity Light texture opacity, on `[0, 1]`. + */ + void set_light_texture_opacity(float opacity); + + /** + * Sets the scale of the light texture. + * + * @param scale Scale of the light texture. + */ + void set_light_texture_scale(const float2& scale); + /// Returns the light texture for this light, or `nullptr` if no light texture is set. const gl::texture_2d* get_light_texture() const; @@ -146,9 +157,8 @@ public: /// Returns the light texture scale tween. const tween& get_light_texture_scale_tween() const; - - /// @copydoc object_base::update_tweens(); - virtual void update_tweens(); + + /// @} private: virtual void transformed();