Browse Source

Improve shadow map pass

master
C. J. Howard 1 year ago
parent
commit
915c5582c5
6 changed files with 58 additions and 43 deletions
  1. +2
    -2
      src/game/world.cpp
  2. +5
    -0
      src/render/passes/material-pass.cpp
  3. +1
    -0
      src/render/passes/material-pass.hpp
  4. +9
    -10
      src/render/passes/shadow-map-pass.cpp
  5. +1
    -1
      src/scene/directional-light.cpp
  6. +40
    -30
      src/scene/directional-light.hpp

+ 2
- 2
src/game/world.cpp View File

@ -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

+ 5
- 0
src/render/passes/material-pass.cpp View File

@ -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<scene::object_base*>* 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");

+ 1
- 0
src/render/passes/material-pass.hpp View File

@ -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;

+ 9
- 10
src/render/passes/shadow-map-pass.cpp View File

@ -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<float> subfrustum(subfrustum_projection * camera_view);
geom::view_frustum<float> subfrustum(subfrustum_projection * ctx.view);
// Create AABB containing the view camera subfrustum corners
const std::array<float3, 8>& 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;

+ 1
- 1
src/scene/directional-light.cpp View File

@ -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),

+ 40
- 30
src/scene/directional-light.hpp View File

@ -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<float2>& get_light_texture_scale_tween() const;
/// @copydoc object_base::update_tweens();
virtual void update_tweens();
/// @}
private:
virtual void transformed();

Loading…
Cancel
Save