Unravel Engine C++ Reference
Loading...
Searching...
No Matches
shadow.h
Go to the documentation of this file.
1#pragma once
2#include "glm/gtc/type_ptr.hpp"
3#include <engine/engine_export.h>
4
5#include <engine/ecs/ecs.h>
11
12#include <base/basetypes.hpp>
13#include <context/context.hpp>
14
15#include <engine/ecs/ecs.h>
17#include <graphics/graphics.h>
18#include <hpp/small_vector.hpp>
19
20namespace unravel
21{
22namespace shadow
23{
35
37{
38 enum Enum
39 {
42
43 Count
44 };
45};
46
48{
49 enum Enum
50 {
53
54 Count
55 };
56};
57
58struct SmImpl
59{
60 enum Enum
61 {
67
68 Count
69 };
70};
71
72struct SmType
73{
74 enum Enum
75 {
79
80 Count
81 };
82};
83
85{
86 enum Enum
87 {
92
93 Count
94 };
95};
96
98{
99 enum Enum
100 {
103
104 Count
105 };
106};
107
120
122{
123 float m_x;
124 float m_y;
125 float m_z;
126 uint32_t m_normal;
127 float m_u;
128 float m_v;
129};
130
131struct Light
132{
134 {
135 struct
136 {
137 float m_x;
138 float m_y;
139 float m_z;
140 float m_w;
141 };
142
143 float m_v[4];
144 };
145
147 {
148 struct
149 {
150 float m_x;
151 float m_y;
152 float m_z;
153 float m_inner;
154 };
155
156 float m_v[4];
157 };
158
161};
162
164{
165 void init()
166 {
167 m_ambientPass = 1.0f;
168 m_lightingPass = 1.0f;
169
170 m_shadowMapBias = 0.003f;
171 m_shadowMapOffset = 0.0f;
172 m_shadowMapParam0 = 0.5;
173 m_shadowMapParam1 = 1.0;
174 m_depthValuePow = 1.0f;
175 m_showSmCoverage = 1.0f;
176 m_shadowMapTexelSize = 1.0f / 512.0f;
177
178 m_csmFarDistances[0] = 30.0f;
179 m_csmFarDistances[1] = 90.0f;
180 m_csmFarDistances[2] = 180.0f;
181 m_csmFarDistances[3] = 1000.0f;
182
183 m_tetraNormalGreen[0] = 0.0f;
184 m_tetraNormalGreen[1] = -0.57735026f;
185 m_tetraNormalGreen[2] = 0.81649661f;
186
187 m_tetraNormalYellow[0] = 0.0f;
188 m_tetraNormalYellow[1] = -0.57735026f;
189 m_tetraNormalYellow[2] = -0.81649661f;
190
191 m_tetraNormalBlue[0] = -0.81649661f;
192 m_tetraNormalBlue[1] = 0.57735026f;
193 m_tetraNormalBlue[2] = 0.0f;
194
195 m_tetraNormalRed[0] = 0.81649661f;
196 m_tetraNormalRed[1] = 0.57735026f;
197 m_tetraNormalRed[2] = 0.0f;
198
199 m_XNum = 2.0f;
200 m_YNum = 2.0f;
201 m_XOffset = 10.0f / 512.0f;
202 m_YOffset = 10.0f / 512.0f;
203
204 u_params0 = bgfx::createUniform("u_params0", bgfx::UniformType::Vec4);
205 u_params1 = bgfx::createUniform("u_params1", bgfx::UniformType::Vec4);
206 u_params2 = bgfx::createUniform("u_params2", bgfx::UniformType::Vec4);
207 u_color = bgfx::createUniform("u_color", bgfx::UniformType::Vec4);
208 u_smSamplingParams = bgfx::createUniform("u_smSamplingParams", bgfx::UniformType::Vec4);
209 u_csmFarDistances = bgfx::createUniform("u_csmFarDistances", bgfx::UniformType::Vec4);
210 u_lightMtx = bgfx::createUniform("u_lightMtx", bgfx::UniformType::Mat4);
211
212 u_tetraNormalGreen = bgfx::createUniform("u_tetraNormalGreen", bgfx::UniformType::Vec4);
213 u_tetraNormalYellow = bgfx::createUniform("u_tetraNormalYellow", bgfx::UniformType::Vec4);
214 u_tetraNormalBlue = bgfx::createUniform("u_tetraNormalBlue", bgfx::UniformType::Vec4);
215 u_tetraNormalRed = bgfx::createUniform("u_tetraNormalRed", bgfx::UniformType::Vec4);
216
217 u_shadowMapMtx0 = bgfx::createUniform("u_shadowMapMtx0", bgfx::UniformType::Mat4);
218 u_shadowMapMtx1 = bgfx::createUniform("u_shadowMapMtx1", bgfx::UniformType::Mat4);
219 u_shadowMapMtx2 = bgfx::createUniform("u_shadowMapMtx2", bgfx::UniformType::Mat4);
220 u_shadowMapMtx3 = bgfx::createUniform("u_shadowMapMtx3", bgfx::UniformType::Mat4);
221
222 u_shadowCutoutBaseColor = bgfx::createUniform("u_base_color", bgfx::UniformType::Vec4);
223 u_shadowCutoutSurfaceData = bgfx::createUniform("u_surface_data", bgfx::UniformType::Vec4);
224 u_shadowCutoutTiling = bgfx::createUniform("u_tiling", bgfx::UniformType::Vec4);
225 s_shadowCutoutColor = bgfx::createUniform("s_tex_color", bgfx::UniformType::Sampler);
226 }
227
228 void setPtrs(Light* _lightPtr,
229 float* _colorPtr,
230 float* _lightMtxPtr,
231 float* _shadowMapMtx0,
232 float* _shadowMapMtx1,
233 float* _shadowMapMtx2,
234 float* _shadowMapMtx3)
235 {
236 m_lightMtxPtr = _lightMtxPtr;
237 m_colorPtr = _colorPtr;
238 m_lightPtr = _lightPtr;
239
240 m_shadowMapMtx0 = _shadowMapMtx0;
241 m_shadowMapMtx1 = _shadowMapMtx1;
242 m_shadowMapMtx2 = _shadowMapMtx2;
243 m_shadowMapMtx3 = _shadowMapMtx3;
244 }
245
246 // Call this once at initialization (frame uniforms persist until changed).
248 {
249 bgfx::setUniform(u_tetraNormalGreen, m_tetraNormalGreen);
250 bgfx::setUniform(u_tetraNormalYellow, m_tetraNormalYellow);
251 bgfx::setUniform(u_tetraNormalBlue, m_tetraNormalBlue);
252 bgfx::setUniform(u_tetraNormalRed, m_tetraNormalRed);
253 }
254
255 // Call this once per frame.
257 {
258 bgfx::setUniform(u_params1, m_params1);
259 bgfx::setUniform(u_params2, m_params2);
260 bgfx::setUniform(u_smSamplingParams, m_paramsBlur);
261 bgfx::setUniform(u_csmFarDistances, m_csmFarDistances);
262 }
263
264 // Call this before each draw call.
266 {
269 bgfx::setUniform(u_shadowMapMtx0, m_shadowMapMtx0);
270 bgfx::setUniform(u_shadowMapMtx1, m_shadowMapMtx1);
271 bgfx::setUniform(u_shadowMapMtx2, m_shadowMapMtx2);
272 bgfx::setUniform(u_shadowMapMtx3, m_shadowMapMtx3);
273
274 bgfx::setUniform(u_params0, m_params0);
275 bgfx::setUniform(u_lightMtx, m_lightMtxPtr);
276 bgfx::setUniform(u_color, m_colorPtr);
277 }
278
280 {
281 if(cutout.color_map)
282 {
283 bgfx::setTexture(0, s_shadowCutoutColor, cutout.color_map->native_handle());
284 }
285 bgfx::setUniform(u_shadowCutoutBaseColor, math::value_ptr(cutout.base_color.value));
286 const math::vec4 surface_data{0.0f, 0.0f, 0.0f, cutout.alpha_test_value};
287 bgfx::setUniform(u_shadowCutoutSurfaceData, math::value_ptr(surface_data));
288 const math::vec4 tiling{cutout.tiling.x, cutout.tiling.y, 0.0f, 0.0f};
289 bgfx::setUniform(u_shadowCutoutTiling, math::value_ptr(tiling));
290 }
291
292 void destroy()
293 {
294 auto safe_destroy = [](bgfx::UniformHandle& handle)
295 {
296 if(bgfx::isValid(handle))
297 {
298 bgfx::destroy(handle);
299 handle = {bgfx::kInvalidHandle};
300 }
301 };
302 safe_destroy(u_params0);
303 safe_destroy(u_params1);
304 safe_destroy(u_params2);
305 safe_destroy(u_color);
306 safe_destroy(u_smSamplingParams);
307 safe_destroy(u_csmFarDistances);
308
309 safe_destroy(u_tetraNormalGreen);
310 safe_destroy(u_tetraNormalYellow);
311 safe_destroy(u_tetraNormalBlue);
312 safe_destroy(u_tetraNormalRed);
313
314 safe_destroy(u_shadowMapMtx0);
315 safe_destroy(u_shadowMapMtx1);
316 safe_destroy(u_shadowMapMtx2);
317 safe_destroy(u_shadowMapMtx3);
318
319 safe_destroy(u_shadowCutoutBaseColor);
320 safe_destroy(u_shadowCutoutSurfaceData);
321 safe_destroy(u_shadowCutoutTiling);
322 safe_destroy(s_shadowCutoutColor);
323
324 safe_destroy(u_lightMtx);
325 }
326
327 union
328 {
329 struct
330 {
335 };
336
337 float m_params0[4];
338 };
339
340 union
341 {
342 struct
343 {
348 };
349
350 float m_params1[4];
351 };
352
353 union
354 {
355 struct
356 {
361 };
362
363 float m_params2[4];
364 };
365
366 union
367 {
368 struct
369 {
370 float m_XNum;
371 float m_YNum;
374 };
375
376 float m_paramsBlur[4];
377 };
378
384
392
393private:
394 bgfx::UniformHandle u_params0;
395 bgfx::UniformHandle u_params1;
396 bgfx::UniformHandle u_params2;
397 bgfx::UniformHandle u_color;
398 bgfx::UniformHandle u_smSamplingParams;
399 bgfx::UniformHandle u_csmFarDistances;
400
401 bgfx::UniformHandle u_tetraNormalGreen;
402 bgfx::UniformHandle u_tetraNormalYellow;
403 bgfx::UniformHandle u_tetraNormalBlue;
404 bgfx::UniformHandle u_tetraNormalRed;
405
406 bgfx::UniformHandle u_shadowMapMtx0;
407 bgfx::UniformHandle u_shadowMapMtx1;
408 bgfx::UniformHandle u_shadowMapMtx2;
409 bgfx::UniformHandle u_shadowMapMtx3;
410
411 bgfx::UniformHandle u_shadowCutoutBaseColor;
412 bgfx::UniformHandle u_shadowCutoutSurfaceData;
413 bgfx::UniformHandle u_shadowCutoutTiling;
414 bgfx::UniformHandle s_shadowCutoutColor;
415
416 bgfx::UniformHandle u_lightMtx;
417};
418
440
441struct PosColorTexCoord0Vertex : gfx::vertex<PosColorTexCoord0Vertex>
442{
443 float m_x;
444 float m_y;
445 float m_z;
446 uint32_t m_rgba;
447 float m_u;
448 float m_v;
449
450 static void init(gfx::vertex_layout& decl)
451 {
452 decl.begin()
453 .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
454 .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
455 .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
456 .end();
457 }
458};
459
460struct PosVertex : gfx::vertex<PosVertex>
461{
462 float m_x;
463 float m_y;
464 float m_z;
465 static void init(gfx::vertex_layout& decl)
466 {
467 decl.begin().add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float).end();
468 }
469};
470
472{
473 void init(rtti::context& ctx);
474
475 void destroy()
476 {
477 // Pack depth.
478 for(uint8_t ii = 0; ii < DepthImpl::Count; ++ii)
479 {
480 for(uint8_t jj = 0; jj < PackDepth::Count; ++jj)
481 {
482 m_packDepth[ii][jj].reset();
483 m_packDepthInstanced[ii][jj].reset();
484 m_packDepthSkinned[ii][jj].reset();
485 m_packDepthCutout[ii][jj].reset();
486 m_packDepthInstancedCutout[ii][jj].reset();
487 m_packDepthSkinnedCutout[ii][jj].reset();
488 }
489 }
490
491 // Draw depth.
492 for(uint8_t ii = 0; ii < PackDepth::Count; ++ii)
493 {
494 m_drawDepth[ii].reset();
495 }
496
497 // Hblur.
498 for(uint8_t ii = 0; ii < PackDepth::Count; ++ii)
499 {
500 m_hBlur[ii].reset();
501 }
502
503 // Vblur.
504 for(uint8_t ii = 0; ii < PackDepth::Count; ++ii)
505 {
506 m_vBlur[ii].reset();
507 }
508
509 // Misc.
510 m_black.reset();
511 }
512
523};
524
526{
527#define SHADOW_FLOAT_PARAM(_name) \
528 float _name{}, _name##Min{}, _name##Max{}, _name##Step \
529 { \
530 }
531 SHADOW_FLOAT_PARAM(m_sizePwrTwo);
532 SHADOW_FLOAT_PARAM(m_depthValuePow);
536 SHADOW_FLOAT_PARAM(m_normalOffset);
537 SHADOW_FLOAT_PARAM(m_customParam0);
538 SHADOW_FLOAT_PARAM(m_customParam1);
543 bool m_doBlur{};
547#undef SHADOW_FLOAT_PARAM
548};
549
569
571{
572 ClearValues(uint32_t _clearRgba = 0x30303000, float _clearDepth = 1.0f, uint8_t _clearStencil = 0)
573 : clear_rgba(_clearRgba)
574 , clear_depth(_clearDepth)
575 , clear_stencil(_clearStencil)
576 {
577 }
578
579 uint32_t clear_rgba;
582};
583
585{
586 enum Enum
587 {
588 legacy, // Original fixed frustum calculation
589 adaptive, // Altitude-aware adaptive frustum
590 hybrid, // Combination of both approaches
591
592 count
593 };
594};
595
597{
598 enum Enum
599 {
600 none = 0,
601 altitude_compensation = 1 << 0, // Adjust frustum based on camera altitude
602 scene_bounds_fitting = 1 << 1, // Fit to actual scene bounds
603 dynamic_split_weights = 1 << 2, // Adjust split distribution dynamically
604 stabilized_light_matrix = 1 << 3, // Improve light matrix positioning
605
607 };
608};
609
611{
612 float altitude_scale_factor = 0.5f; // How much altitude affects frustum extension
613 float min_altitude_boost = 0.05f; // Minimum altitude compensation
614 float max_altitude_boost = 100.0f; // Maximum altitude compensation
615 float scene_bounds_margin = 1.2f; // Margin factor for scene bounds fitting
616 float split_weight_bias = 0.1f; // Bias for dynamic split weight adjustment
617};
618
624using shadow_map_models_t = hpp::small_vector<shadow_visibility_data>;
625
654{
655public:
658
659 void init(rtti::context& ctx);
660 void deinit();
661 void deinit_textures();
662 void deinit_uniforms();
663
664 void update(const camera& cam, const light& l, const math::transform& ltrans, bool is_active);
665 auto already_updated() const -> bool;
666
668
669 auto get_depth_type() const -> PackDepth::Enum;
670 auto get_rt_texture(uint8_t split) const -> bgfx::TextureHandle;
672 void submit_uniforms(uint8_t stage) const;
673
674 // Configuration methods for improved shadow mapping
675 void set_frustum_calculation_method(frustum_calculation_method::Enum method) { frustum_method_ = method; }
676 auto get_frustum_calculation_method() const -> frustum_calculation_method::Enum { return frustum_method_; }
677
678 void set_csm_optimization_flags(uint32_t flags) { csm_optimization_flags_ = flags; }
679 auto get_csm_optimization_flags() const -> uint32_t { return csm_optimization_flags_; }
680
681 void enable_adaptive_shadows(bool enable) {
682 if(enable) {
683 frustum_method_ = frustum_calculation_method::adaptive;
684 csm_optimization_flags_ = csm_optimization_flags::all;
685 } else {
686 frustum_method_ = frustum_calculation_method::legacy;
687 csm_optimization_flags_ = csm_optimization_flags::none;
688 }
689 }
690
691 // Adaptive parameter configuration methods
692 void set_adaptive_params(const adaptive_shadow_params& params) { adaptive_params_ = params; }
693 auto get_adaptive_params() const -> const adaptive_shadow_params& { return adaptive_params_; }
694
695 void set_altitude_scale_factor(float factor) { adaptive_params_.altitude_scale_factor = factor; }
696 auto get_altitude_scale_factor() const -> float { return adaptive_params_.altitude_scale_factor; }
697
698 void set_altitude_boost_range(float min_boost, float max_boost) {
699 adaptive_params_.min_altitude_boost = min_boost;
700 adaptive_params_.max_altitude_boost = max_boost;
701 }
702
703 auto get_min_altitude_boost() const -> float { return adaptive_params_.min_altitude_boost; }
704 auto get_max_altitude_boost() const -> float { return adaptive_params_.max_altitude_boost; }
705
706private:
707 auto render_scene_into_shadowmap(uint8_t shadowmap_1_id,
708 const shadow_map_models_t& models,
710 ShadowMapSettings* currentSmSettings,
711 const camera* cam,
712 ::unravel::rendering::pipeline_stats* stats = nullptr) -> bool;
713
714 void submit_batched_shadow_geometry_cascade(shadow_batch_collector& collector,
715 uint8_t viewId,
716 ShadowMapSettings* currentSmSettings,
717 const RenderState& renderState,
718 ::unravel::rendering::pipeline_stats* stats = nullptr);
719
720 ClearValues clear_values_;
721
722 float color_[4];
723 Light point_light_;
724 Light directional_light_;
725
726 float light_mtx_[16];
727 float shadow_map_mtx_[ShadowMapRenderTargets::Count][16];
728
730 SceneSettings settings_;
731
732 uint16_t current_shadow_map_size_{};
733 uint8_t current_num_splits_{};
734
735 Uniforms uniforms_;
736 Programs programs_;
737
738 float light_view_[ShadowMapRenderTargets::Count][16];
739 float light_proj_[ShadowMapRenderTargets::Count][16];
740
742
743 bgfx::UniformHandle tex_color_{bgfx::kInvalidHandle};
744 bgfx::UniformHandle shadow_map_[ShadowMapRenderTargets::Count];
745 bgfx::FrameBufferHandle rt_shadow_map_[ShadowMapRenderTargets::Count];
746 bgfx::FrameBufferHandle rt_blur_{bgfx::kInvalidHandle};
747
748 bool valid_{};
749
750 uint64_t last_update_ = -1;
751
752 // Static mesh batching system for shadow maps - one collector per cascade/view
753 std::vector<shadow_batch_collector> cascade_batch_collectors_;
754
755 std::shared_ptr<int> sentinel_ = std::make_shared<int>(0);
756
757 // New configuration members
759 uint32_t csm_optimization_flags_ = csm_optimization_flags::none;
760
761 // Additional parameters for adaptive calculations
762 adaptive_shadow_params adaptive_params_;
763};
764
765} // namespace shadow
766} // namespace unravel
Storage for frustum planes / values and wraps up common functionality.
Definition frustum.h:18
General purpose transformation class designed to maintain each component of the transformation separa...
Definition transform.hpp:27
Class representing a camera. Contains functionality for manipulating and updating a camera....
Definition camera.h:62
Class representing a GPU program.
Definition gpu_program.h:17
std::shared_ptr< gpu_program > ptr
Definition gpu_program.h:19
Structure describing a LOD group (set of meshes), LOD transitions, and their materials.
Definition model.h:275
Shadow mapping generator with improved algorithms for high-altitude cameras.
Definition shadow.h:654
void set_adaptive_params(const adaptive_shadow_params &params)
Definition shadow.h:692
auto get_csm_optimization_flags() const -> uint32_t
Definition shadow.h:679
auto get_frustum_calculation_method() const -> frustum_calculation_method::Enum
Definition shadow.h:676
auto get_adaptive_params() const -> const adaptive_shadow_params &
Definition shadow.h:693
auto get_min_altitude_boost() const -> float
Definition shadow.h:703
auto get_depth_type() const -> PackDepth::Enum
Definition shadow.cpp:1098
void submit_uniforms(uint8_t stage) const
Definition shadow.cpp:1119
auto get_rt_texture(uint8_t split) const -> bgfx::TextureHandle
Definition shadow.cpp:1104
auto get_max_altitude_boost() const -> float
Definition shadow.h:704
void set_altitude_boost_range(float min_boost, float max_boost)
Definition shadow.h:698
void update(const camera &cam, const light &l, const math::transform &ltrans, bool is_active)
Definition shadow.cpp:1145
void generate_shadowmaps(const shadow_map_models_t &model, const camera &cam, ::unravel::rendering::pipeline_stats *stats=nullptr)
Definition shadow.cpp:1834
void init(rtti::context &ctx)
Definition shadow.cpp:448
void set_csm_optimization_flags(uint32_t flags)
Definition shadow.h:678
auto already_updated() const -> bool
Definition shadow.cpp:1140
void set_altitude_scale_factor(float factor)
Definition shadow.h:695
auto get_depth_render_program(PackDepth::Enum depth) const -> gpu_program::ptr
Definition shadow.cpp:1114
void set_frustum_calculation_method(frustum_calculation_method::Enum method)
Definition shadow.h:675
auto get_altitude_scale_factor() const -> float
Definition shadow.h:696
void enable_adaptive_shadows(bool enable)
Definition shadow.h:681
bgfx::VertexLayout vertex_layout
Definition vertex_decl.h:8
hpp::small_vector< shadow_visibility_data > shadow_map_models_t
Definition shadow.h:624
vec4 value
Definition color.h:80
Struct representing a light.
Definition light.h:87
Contains level of detail (LOD) data for an entity per view. Uses distance-based hysteresis for stable...
Definition model.h:34
ClearValues(uint32_t _clearRgba=0x30303000, float _clearDepth=1.0f, uint8_t _clearStencil=0)
Definition shadow.h:572
SpotDirectionInner m_spotDirectionInner
Definition shadow.h:160
static void init(gfx::vertex_layout &decl)
Definition shadow.h:450
static void init(gfx::vertex_layout &decl)
Definition shadow.h:465
gpu_program::ptr m_packDepthSkinned[DepthImpl::Count][PackDepth::Count]
Definition shadow.h:518
gpu_program::ptr m_hBlur[PackDepth::Count]
Definition shadow.h:515
gpu_program::ptr m_black
Definition shadow.h:513
gpu_program::ptr m_packDepth[DepthImpl::Count][PackDepth::Count]
Definition shadow.h:517
gpu_program::ptr m_packDepthInstanced[DepthImpl::Count][PackDepth::Count]
Definition shadow.h:519
void init(rtti::context &ctx)
Definition shadow.cpp:2534
gpu_program::ptr m_drawDepth[PackDepth::Count]
Definition shadow.h:516
gpu_program::ptr m_packDepthSkinnedCutout[DepthImpl::Count][PackDepth::Count]
Definition shadow.h:521
gpu_program::ptr m_packDepthInstancedCutout[DepthImpl::Count][PackDepth::Count]
Definition shadow.h:522
gpu_program::ptr m_packDepthCutout[DepthImpl::Count][PackDepth::Count]
Definition shadow.h:520
gpu_program::ptr m_vBlur[PackDepth::Count]
Definition shadow.h:514
DepthImpl::Enum m_depthImpl
Definition shadow.h:553
LightType::Enum m_lightType
Definition shadow.h:552
void submitPerFrameUniforms() const
Definition shadow.h:256
void setPtrs(Light *_lightPtr, float *_colorPtr, float *_lightMtxPtr, float *_shadowMapMtx0, float *_shadowMapMtx1, float *_shadowMapMtx2, float *_shadowMapMtx3)
Definition shadow.h:228
void submitPerDrawUniforms() const
Definition shadow.h:265
void submitConstUniforms() const
Definition shadow.h:247
float m_tetraNormalYellow[3]
Definition shadow.h:380
void submitShadowCutoutState(const shadow_cutout_state &cutout) const
Definition shadow.h:279
float m_tetraNormalGreen[3]
Definition shadow.h:379
Per-draw state for alpha-cutout shadow batches (texture + clip threshold).
Definition batch_key.h:105
std::shared_ptr< gfx::texture > color_map
Definition batch_key.h:106
gfx::uniform_handle handle
Definition uniform.cpp:9