59 m_shader_template_definitions[
"MAX_BONE_COUNT"] = std::to_string(m_max_bone_count);
67 rebuild_static_mesh_shader_program();
76 rebuild_skeletal_mesh_shader_program();
95 if (!directional_light.is_shadow_caster())
107 if (!directional_light.get_shadow_framebuffer())
113 render_shadow_atlas(ctx, directional_light);
121 if (m_max_bone_count != bone_count)
123 m_max_bone_count = bone_count;
126 m_shader_template_definitions[
"MAX_BONE_COUNT"] = std::to_string(m_max_bone_count);
129 rebuild_skeletal_mesh_shader_program();
149 (plane.normal.x() > 0.0f) ? box.max.x() : box.min.x(),
150 (plane.normal.y() > 0.0f) ? box.max.y() : box.min.y(),
151 (plane.normal.z() > 0.0f) ? box.max.z() : box.min.z()
154 return plane.distance(p) < 0.0f;
179 const auto& object_bounds = object->
get_bounds();
180 if (box_outside_plane(object_bounds, light_view_frustum.left()) ||
181 box_outside_plane(object_bounds, light_view_frustum.right()) ||
182 box_outside_plane(object_bounds, light_view_frustum.bottom()) ||
183 box_outside_plane(object_bounds, light_view_frustum.top()) ||
184 box_outside_plane(object_bounds, light_view_frustum.near()))
210 bool two_sided =
false;
226 for (
unsigned int i = 0;
i < cascade_count - 1; ++
i)
228 const float weight =
static_cast<float>(
i + 1) /
static_cast<float>(cascade_count);
240 const auto cascade_resolution = atlas_resolution >> 1;
243 std::sort(std::execution::par_unseq, ctx.
operations.begin(), ctx.
operations.end(), operation_compare);
247 for (
unsigned int i = 0;
i < cascade_count; ++
i)
250 const auto subfrustum_near =
i ? cascade_distances[
i - 1] : camera.
get_clip_near();
251 const auto subfrustum_far = cascade_distances[
i];
254 const auto subfrustum_centroid = camera.
get_translation() + camera.
get_forward() * ((subfrustum_near + subfrustum_far) * 0.5f);
261 const auto subfrustum_inv_view_projection = camera.
get_inv_view() * subfrustum_inv_projection;
264 const auto ndc_to_light_view = light_view * subfrustum_inv_view_projection;
268 for (std::size_t j = 0;
j < 8; ++
j)
284 const auto corner = ndc_to_light_view * ndc_cube[
j];
293 light_projection_bounds.
min.
x(), light_projection_bounds.
max.
x(),
294 light_projection_bounds.
min.
y(), light_projection_bounds.
max.
y(),
295 -light_projection_bounds.
min.
z(), -light_projection_bounds.
max.
z()
299 const auto light_view_projection = light_projection * light_view;
300 const auto light_view_translation =
math::fvec4(subfrustum_centroid);
305 const auto vs_subfrustum_centroid =
math::fvec3{0.0f, 0.0f, ((subfrustum_near + subfrustum_far) * -0.5f)};
309 const auto vs_light_view =
math::look_at_rh(vs_subfrustum_centroid, vs_subfrustum_centroid + vs_light_direction, vs_light_up);
310 const auto vs_light_view_projection = light_projection * vs_light_view;
316 queue(ctx, light, light_view_projection);
325 static_cast<float>(
static_cast<int>(
i % 2) * cascade_resolution),
326 static_cast<float>(
static_cast<int>(
i >> 1) * cascade_resolution),
327 static_cast<float>(cascade_resolution),
328 static_cast<float>(cascade_resolution)
361 if (active_shader_program != shader_program)
363 active_shader_program = shader_program;
370 model_view[3] -= light_view_translation;
371 model_view = light_view_rotation * model_view;
372 const auto model_view_projection = light_projection * model_view;
375 if (active_shader_program == m_static_mesh_shader_program.get())
377 m_static_mesh_model_view_projection_var->
update(model_view_projection);
379 else if (active_shader_program == m_skeletal_mesh_shader_program.get())
381 m_skeletal_mesh_model_view_projection_var->
update(model_view_projection);
397 void cascaded_shadow_map_stage::rebuild_static_mesh_shader_program()
399 m_static_mesh_shader_program = m_static_mesh_shader_template->build(m_shader_template_definitions);
400 if (!m_static_mesh_shader_program->linked())
402 debug::log_error(
"Failed to build cascaded shadow map shader program for static meshes: {}", m_static_mesh_shader_program->info());
405 m_static_mesh_model_view_projection_var =
nullptr;
409 m_static_mesh_model_view_projection_var = m_static_mesh_shader_program->variable(
"model_view_projection");
413 void cascaded_shadow_map_stage::rebuild_skeletal_mesh_shader_program()
415 m_skeletal_mesh_shader_program = m_skeletal_mesh_shader_template->build(m_shader_template_definitions);
416 if (!m_skeletal_mesh_shader_program->linked())
418 debug::log_error(
"Failed to build cascaded shadow map shader program for skeletal meshes: {}", m_skeletal_mesh_shader_program->info());
421 m_skeletal_mesh_model_view_projection_var =
nullptr;
422 m_skeletal_mesh_matrix_palette_var =
nullptr;
426 m_skeletal_mesh_model_view_projection_var = m_skeletal_mesh_shader_program->variable(
"model_view_projection");
427 m_skeletal_mesh_matrix_palette_var = m_skeletal_mesh_shader_program->variable(
"matrix_palette");
433 const bool skinned_a = !
a->matrix_palette.empty();
434 const bool skinned_b = !
b->matrix_palette.empty();
435 const bool two_sided_a = (
a->material) ?
a->material->is_two_sided() :
false;
436 const bool two_sided_b = (
b->material) ?
b->material->is_two_sided() :
false;
448 return (
a->vertex_array <
b->vertex_array);
466 return (
a->vertex_array <
b->vertex_array);
491 return (
a->vertex_array <
b->vertex_array);
509 return (
a->vertex_array <
b->vertex_array);
Graphics pipeline interface.
void set_primitive_topology(primitive_topology topology)
Sets the primitive topology to use for drawing.
void clear_attachments(std::uint8_t mask, const clear_value &value)
Clears the color, depth, or stencil buffers of current attachments.
void bind_shader_program(const gl::shader_program *shader_program)
Sets the vertex input.
void bind_framebuffer(const gl::framebuffer *framebuffer)
Sets the vertex input.
void set_depth_clamp_enabled(bool enabled)
Controls whether depth clamping is enabled.
void set_color_blend_enabled(bool enabled)
Controls whether blending is enabled for the corresponding color attachment.
void set_cull_mode(cull_mode mode)
Sets the triangle culling mode.
void set_viewport(std::uint32_t first_viewport, std::span< const viewport > viewports)
Sets one or more viewports.
void set_depth_write_enabled(bool enabled)
Controls whether depth writes are enabled.
void bind_vertex_buffers(std::uint32_t first_binding, std::span< const vertex_buffer *const > buffers, std::span< const std::size_t > offsets, std::span< const std::size_t > strides)
Binds vertex buffers.
void set_depth_compare_op(gl::compare_op compare_op)
Sets the depth comparison operator.
void draw(std::uint32_t vertex_count, std::uint32_t instance_count, std::uint32_t first_vertex, std::uint32_t first_instance)
Draws primitives.
void set_depth_test_enabled(bool enabled)
Controls whether depth testing is enabled.
void bind_vertex_array(const vertex_array *array)
Binds a vertex array.
Shader program which can be linked to shader objects and executed.
Template used to for generating one or more shader variants from a single source.
virtual void update(bool value) const
Updates the value of the variable.
void execute(render::context &ctx) override
Executes the render stage.
void set_max_bone_count(std::size_t bone_count)
Sets the maximum bone count for shadow-casting skeletal meshes.
cascaded_shadow_map_stage(gl::pipeline &pipeline, ::resource_manager &resource_manager)
Constructs a cascaded shadow map stage.
A material is associated with exactly one shader program and contains a set of material properties wh...
material_shadow_mode get_shadow_mode() const noexcept
Returns the material shadow mode.
bool is_two_sided() const noexcept
Returns true if the material surface is two-sided, and false otherwise.
Manages the loading, caching, and saving of resources.
std::shared_ptr< T > load(const std::filesystem::path &path)
Loads and caches a resource.
constexpr float get_aspect_ratio() const noexcept
Returns the camera's aspect ratio.
constexpr const math::fvec3 & get_forward() const noexcept
Returns the camera's forward vector.
constexpr float get_clip_near() const noexcept
Returns the signed distance to the camera's near clipping plane.
constexpr float get_vertical_fov() const noexcept
Returns the camera's vertical field of view, in radians.
constexpr const math::fmat4 & get_inv_view() const noexcept
Returns the inverse of the camera's view matrix.
const std::vector< object_base * > & get_objects() const noexcept
Returns all objects in the collection.
Light source with parallel rays and constant intensity.
constexpr const std::shared_ptr< gl::framebuffer > & get_shadow_framebuffer() const noexcept
Returns the shadow map framebuffer, of nullptr if no shadow map framebuffer is set.
constexpr const math::fvec4 & get_shadow_cascade_distances() const noexcept
Returns the array of shadow cascade far clipping plane distances.
constexpr float get_shadow_max_distance() const noexcept
Returns the maximum distance from a camera's near clipping plane up to which shadows are visible.
constexpr std::span< const math::fmat4 > get_shadow_cascade_matrices() const noexcept
Returns the array of world-space to cascade texture-space transformation matrices.
constexpr const math::fvec3 & get_direction() const noexcept
Returns a unit vector pointing in the light direction.
constexpr unsigned int get_shadow_cascade_count() const noexcept
Returns the number of shadow cascades.
constexpr float get_shadow_cascade_distribution() const noexcept
Returns the shadow cascade distribution weight.
constexpr std::span< const math::fmat4 > get_shadow_scale_bias_matrices() const noexcept
Returns the array of shadow cascade scale-bias matrices.
Abstract base class for light objects.
Abstract base class for scene objects.
virtual const aabb_type & get_bounds() const noexcept=0
Returns the bounds of the object.
constexpr std::uint32_t get_layer_mask() const noexcept
Returns the layer mask of the object.
virtual const std::size_t get_object_type_id() const noexcept=0
Returns the type ID for this scene object type.
constexpr const vector_type & get_translation() const noexcept
Returns the translation of the object.
virtual void render(render::context &ctx) const
Adds render operations to a render context.
constexpr const quaternion_type & get_rotation() const noexcept
Returns the rotation of the object.
static const std::atomic< std::size_t > object_type_id
Unique type ID for this scene object type.
log_message< log_message_severity::warning, Args... > log_warning
Formats and logs a warning message.
log_message< log_message_severity::error, Args... > log_error
Formats and logs an error message.
@ none
No triangles are discarded.
@ back
Back-facing triangles are discarded.
@ vertex
Vertex shader stage.
@ depth_clear_bit
Indicates the depth buffer should be cleared.
@ greater
Comparison evaluates reference > test.
constexpr mat4< T > look_at_rh(const vec3< T > &position, const vec3< T > &target, const vec3< T > &up)
Constructs a right-handed viewing transformation matrix.
constexpr mat4< T > ortho_half_z(T left, T right, T bottom, T top, T near, T far) noexcept
Constructs an orthographic projection matrix which will transform the near and far clipping planes to...
T log_lerp(const T &x, const T &y, S a)
Logarithmically interpolates between x and y.
constexpr T lerp(const T &x, const T &y, S a) noexcept
Linearly interpolates between x and y.
std::tuple< mat4< T >, mat4< T > > perspective_half_z_inv(T vertical_fov, T aspect_ratio, T near, T far)
Constructs a perspective projection matrix which will transform the near and far clipping planes to [...
@ bone_index
Vertex bone indices (uvec4)
@ tangent
Vertex tangent (vec4)
@ normal
Vertex normal (vec3)
@ color
Vertex color (vec4)
@ bone_weight
Vertex bone weights (vec4)
@ uv
Vertex UV texture coordinates (vec2)
@ position
Vertex position (vec3)
@ none
Material does not cast shadows.
@ directional
Directional light.
n-dimensional axis-aligned rectangle.
vector_type min
Minimum extent of the hyperrectangle.
vector_type max
Maximum extent of the hyperrectangle.
void extend(const vector_type &point) noexcept
Extends the hyperrectangle to include a point.
Viewport position, dimensions, and depth range.
n by m column-major matrix.
constexpr element_type & x() noexcept
Returns a reference to the first element.
constexpr element_type & y() noexcept
Returns a reference to the second element.
static constexpr vector infinity() noexcept
Returns a vector of infinities, where every element is equal to infinity.
constexpr element_type & z() noexcept
Returns a reference to the third element.
const scene::camera * camera
Pointer to the camera.
scene::collection * collection
Collection of scene objects being rendered.
std::vector< const operation * > operations
Render operations generated by visible objects.
std::uint32_t vertex_count
std::span< const math::fmat4 > matrix_palette
std::size_t vertex_offset
std::size_t vertex_stride
gl::primitive_topology primitive_topology
const gl::vertex_buffer * vertex_buffer
std::shared_ptr< render::material > material
const gl::vertex_array * vertex_array