Blender V4.3
eevee_shadow.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#pragma once
12
13#include "BLI_pool.hh"
14#include "BLI_vector.hh"
15
16#include "GPU_batch.hh"
17
18#include "eevee_camera.hh"
19#include "eevee_material.hh"
20#include "eevee_shader.hh"
22#include "eevee_sync.hh"
23
24namespace blender::eevee {
25
26class Instance;
27class ShadowModule;
28class ShadowPipeline;
29struct Light;
30
31/* To be applied after view matrix. Follow same order as eCubeFace. */
32constexpr static const float shadow_face_mat[6][3][3] = {
33 {{+1, +0, +0}, {+0, +1, +0}, {+0, +0, +1}}, /* Z_NEG */
34 {{+0, +0, -1}, {-1, +0, +0}, {+0, +1, +0}}, /* X_POS */
35 {{+0, +0, +1}, {+1, +0, +0}, {+0, +1, +0}}, /* X_NEG */
36 {{+1, +0, +0}, {+0, +0, -1}, {+0, +1, +0}}, /* Y_POS */
37 {{-1, +0, +0}, {+0, +0, +1}, {+0, +1, +0}}, /* Y_NEG */
38 {{+1, +0, +0}, {+0, -1, +0}, {+0, +0, -1}}, /* Z_POS */
39};
40
41/* Converts to [-SHADOW_TILEMAP_RES / 2..SHADOW_TILEMAP_RES / 2] for XY and [0..1] for Z. */
42constexpr static const float shadow_clipmap_scale_mat[4][4] = {{SHADOW_TILEMAP_RES / 2, 0, 0, 0},
43 {0, SHADOW_TILEMAP_RES / 2, 0, 0},
44 {0, 0, 0.5, 0},
45 {0, 0, 0.5, 1}};
46
47/* Technique used for updating the virtual shadow map contents. */
48enum class ShadowTechnique {
49 /* Default virtual shadow map update using large virtual framebuffer to rasterize geometry with
50 * per-fragment textureAtomicMin to perform depth-test and indirectly store nearest depth value
51 * in the shadow atlas. */
53
54 /* Tile-architecture optimized virtual shadow map update, leveraging on-tile memory for clearing
55 * and depth-testing during geometry rasterization to avoid atomic operations, simplify mesh
56 * depth shader and only perform a single storage operation per pixel. This technique performs
57 * a 3-pass solution, first clearing tiles, updating depth and storing final results. */
59};
60
61/* -------------------------------------------------------------------- */
69
73
75 int level = INT_MAX;
80
81 public:
82 ShadowTileMap(int tiles_index_)
83 {
84 tiles_index = tiles_index_;
85 /* For now just the same index. */
87 /* Avoid uninitialized data. */
88 this->grid_offset = int2(0);
89 this->grid_shift = int2(0);
90 this->set_dirty();
91 }
92
93 void sync_orthographic(const float4x4 &object_mat_,
94 int2 origin_offset,
95 int clipmap_level,
96 eShadowProjectionType projection_type_,
97 uint2 shadow_set_membership_ = ~uint2(0));
98
99 void sync_cubeface(eLightType light_type_,
100 const float4x4 &object_mat,
101 float near,
102 float far,
103 eCubeFace face,
104 uint2 shadow_set_membership_ = ~uint2(0));
105
106 void debug_draw() const;
107
109 {
110 is_dirty = true;
111 }
112
114 {
115 is_dirty = false;
116 }
117};
118
162
164
165/* -------------------------------------------------------------------- */
169
170/* Can be either a shadow caster or a shadow receiver. */
173 bool used = true;
174};
175
177
178/* -------------------------------------------------------------------- */
183
185 friend ShadowPunctual;
186 friend ShadowDirectional;
187 friend ShadowPipeline;
188 friend ShadowTileMapPool;
189
190 public:
191 /* Shadowing technique. */
193
195 ShadowTileMapPool tilemap_pool;
196
199
200 private:
201 Instance &inst_;
202
203 ShadowSceneData &data_;
204
207
208 /* Used to call caster_update_ps_ only once per sync (Initialized on begin_sync). */
209 bool update_casters_ = false;
210
211 /* -------------------------------------------------------------------- */
214
215 PassSimple tilemap_setup_ps_ = {"TilemapSetup"};
216 PassMain tilemap_usage_ps_ = {"TagUsage"};
217 PassSimple tilemap_update_ps_ = {"TilemapUpdate"};
218
219 PassMain::Sub *tilemap_usage_transparent_ps_ = nullptr;
220 gpu::Batch *box_batch_ = nullptr;
221 /* Source texture for depth buffer analysis. */
222 GPUTexture *src_depth_tx_ = nullptr;
223
224 Framebuffer usage_tag_fb;
225
226 PassSimple caster_update_ps_ = {"CasterUpdate"};
227 PassSimple jittered_transparent_caster_update_ps_ = {"TransparentCasterUpdate"};
229 StorageVectorBuffer<uint, 128> past_casters_updated_ = {"PastCastersUpdated"};
230 StorageVectorBuffer<uint, 128> curr_casters_updated_ = {"CurrCastersUpdated"};
231 StorageVectorBuffer<uint, 128> jittered_transparent_casters_ = {"JitteredTransparentCasters"};
233 StorageVectorBuffer<uint, 128> curr_casters_ = {"CurrCasters"};
234
236 DispatchIndirectBuf clear_dispatch_buf_ = {"clear_dispatch_buf"};
238 DrawIndirectBuf tile_draw_buf_ = {"tile_draw_buf"};
240 StorageArrayBuffer<uint, SHADOW_RENDER_MAP_SIZE, true> dst_coord_buf_ = {"dst_coord_buf"};
242 StorageArrayBuffer<uint, SHADOW_RENDER_MAP_SIZE, true> src_coord_buf_ = {"src_coord_buf"};
244 StorageArrayBuffer<uint, SHADOW_RENDER_MAP_SIZE, true> render_map_buf_ = {"render_map_buf"};
246 ShadowRenderViewBuf render_view_buf_ = {"render_view_buf"};
247
248 int3 dispatch_depth_scan_size_;
249 int2 usage_tag_fb_resolution_;
250 int usage_tag_fb_lod_ = 5;
251 int max_view_per_tilemap_ = 1;
252 int2 input_depth_extent_;
253
254 /* Statistics that are read back to CPU after a few frame (to avoid stall). */
255 SwapChain<ShadowStatisticsBuf, 5> statistics_buf_;
256
258
259 /* -------------------------------------------------------------------- */
262
263 static constexpr eGPUTextureFormat atlas_type = GPU_R32UI;
265 Texture atlas_tx_ = {"shadow_atlas_tx_"};
266
268 ShadowPageHeapBuf pages_free_data_ = {"PagesFreeBuf"};
270 ShadowPageCacheBuf pages_cached_data_ = {"PagesCachedBuf"};
272 ShadowPagesInfoDataBuf pages_infos_data_ = {"PagesInfosBuf"};
273
274 int3 copy_dispatch_size_;
275 int3 scan_dispatch_size_;
276 int rendering_tilemap_;
277 int rendering_lod_;
278 bool do_full_update_ = true;
279
281
282 /* -------------------------------------------------------------------- */
285
286 class ShadowView : public View {
287 Instance &inst_;
288 ShadowRenderViewBuf &render_view_buf_;
289
290 public:
291 ShadowView(const char *name, Instance &inst, ShadowRenderViewBuf &render_view_buf)
292 : View(name, SHADOW_VIEW_MAX, true), inst_(inst), render_view_buf_(render_view_buf)
293 {
294 }
295
296 protected:
298 virtual void compute_visibility(ObjectBoundsBuf &bounds,
299 ObjectInfosBuf &infos,
300 uint resource_len,
301 bool debug_freeze) override;
302 };
303
305 ShadowView shadow_multi_view_ = {"ShadowMultiView", inst_, render_view_buf_};
307 Framebuffer render_fb_ = {"shadow_write_framebuffer"};
308
309 /* NOTE(Metal): Metal requires memoryless textures to be created which represent attachments in
310 * the shadow write frame-buffer. These textures do not occupy any physical memory, but require a
311 * Texture object containing its parameters. */
312 Texture shadow_depth_fb_tx_ = {"shadow_depth_fb_tx_"};
313 Texture shadow_depth_accum_tx_ = {"shadow_depth_accum_tx_"};
314
316 std::array<int4, 16> multi_viewports_;
317
319
320 /* -------------------------------------------------------------------- */
323
325 PassSimple debug_draw_ps_ = {"Shadow.Debug"};
326
328
330
331 /* Render setting that reduces the LOD for every light. */
332 float global_lod_bias_ = 0.0f;
334 int shadow_page_size_ = SHADOW_PAGE_RES;
336 int shadow_page_len_ = SHADOW_MAX_TILEMAP;
338 bool enabled_ = true;
339
340 public:
341 ShadowModule(Instance &inst, ShadowSceneData &data);
343
344 void init();
345
346 void begin_sync();
348 void sync_object(const Object *ob,
349 const ObjectHandle &handle,
350 const ResourceHandle &resource_handle,
351 bool is_alpha_blend,
352 bool has_transparent_shadows);
353 void end_sync();
354
356
357 /* Update all shadow regions visible inside the view.
358 * If called multiple time for the same view, it will only do the depth buffer scanning
359 * to check any new opaque surfaces.
360 * Expect the HiZ buffer to be up to date.
361 * Needs to be called after `LightModule::set_view();`. */
362 void set_view(View &view, int2 extent);
363
364 void debug_end_sync();
365 void debug_draw(View &view, GPUFrameBuffer *view_fb);
366
367 template<typename PassType> void bind_resources(PassType &pass)
368 {
369 pass.bind_texture(SHADOW_ATLAS_TEX_SLOT, &atlas_tx_);
370 pass.bind_texture(SHADOW_TILEMAPS_TEX_SLOT, &tilemap_pool.tilemap_tx);
371 }
372
374 {
375 return data_;
376 }
377
378 float global_lod_bias() const
379 {
380 return global_lod_bias_;
381 }
382
383 /* Set all shadows to update. To be called before `end_sync`. */
384 void reset()
385 {
386 do_full_update_ = true;
387 }
388
390 static float screen_pixel_radius(const float4x4 &wininv,
391 bool is_perspective,
392 const int2 &extent);
393
394 private:
395 void remove_unused();
396 void debug_page_map_call(DRWPass *pass);
397 bool shadow_update_finished(int loop_count);
398
400 float tilemap_pixel_radius();
401
402 /* Returns the maximum number of view per shadow projection for a single update loop. */
403 int max_view_per_tilemap();
404};
405
407
408/* -------------------------------------------------------------------- */
413
415 private:
416 ShadowModule &shadows_;
418 Vector<ShadowTileMap *> tilemaps_;
419
420 public:
423 : shadows_(other.shadows_), tilemaps_(std::move(other.tilemaps_)){};
424
426 {
427 shadows_.tilemap_pool.release(tilemaps_);
428 }
429
433 void release_excess_tilemaps(const Light &light);
434
438 void end_sync(Light &light);
439};
440
442 private:
443 ShadowModule &shadows_;
445 Vector<ShadowTileMap *> tilemaps_;
447 IndexRange levels_range = IndexRange(0);
448
449 public:
452 : shadows_(other.shadows_), tilemaps_(std::move(other.tilemaps_)){};
453
455 {
456 shadows_.tilemap_pool.release(tilemaps_);
457 }
458
462 void release_excess_tilemaps(const Light &light, const Camera &camera);
463
467 void end_sync(Light &light, const Camera &camera);
468
469 /* Return coverage of the whole tile-map in world unit. */
470 static float coverage_get(int lvl)
471 {
472 /* This function should be kept in sync with shadow_directional_level(). */
473 /* \note If we would to introduce a global scaling option it would be here. */
474 return exp2(lvl);
475 }
476
477 /* Return coverage of a single tile for a tile-map of this LOD in world unit. */
478 static float tile_size_get(int lvl)
479 {
480 return coverage_get(lvl) / SHADOW_TILEMAP_RES;
481 }
482
483 private:
484 IndexRange clipmap_level_range(const Camera &camera);
485 IndexRange cascade_level_range(const Light &light, const Camera &camera);
486
491 void cascade_tilemaps_distribution(Light &light, const Camera &camera);
492 void clipmap_tilemaps_distribution(Light &light, const Camera &camera);
493
494 void cascade_tilemaps_distribution_near_far_points(const Camera &camera,
495 const Light &light,
496 float3 &near_point,
497 float3 &far_point);
498
499 /* Choose between clip-map and cascade distribution of shadow-map precision depending on the
500 * camera projection type and bounds. */
501 static eShadowProjectionType directional_distribution_type_get(const Camera &camera);
502};
503
505
506} // namespace blender::eevee
unsigned int uint
static AppView * view
static void View(GHOST_IWindow *window, bool stereo, int eye=0)
eGPUTextureFormat
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Texture
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
NonCopyable(const NonCopyable &other)=delete
NonMovable(NonMovable &&other)=delete
View(const char *name, int view_len=1, bool procedural=false)
Definition draw_view.hh:59
detail::PassBase< command::DrawMultiBuf > Sub
Definition draw_pass.hh:462
A running instance of the engine.
static float coverage_get(int lvl)
ShadowDirectional(ShadowModule &module)
static float tile_size_get(int lvl)
void end_sync(Light &light, const Camera &camera)
ShadowDirectional(ShadowDirectional &&other)
void release_excess_tilemaps(const Light &light, const Camera &camera)
ShadowModule(Instance &inst, ShadowSceneData &data)
ShadowTileMapPool tilemap_pool
const ShadowSceneData & get_data()
Pool< ShadowDirectional > directional_pool
void bind_resources(PassType &pass)
void debug_draw(View &view, GPUFrameBuffer *view_fb)
static float screen_pixel_radius(const float4x4 &wininv, bool is_perspective, const int2 &extent)
void set_view(View &view, int2 extent)
Pool< ShadowPunctual > punctual_pool
static ShadowTechnique shadow_technique
void sync_object(const Object *ob, const ObjectHandle &handle, const ResourceHandle &resource_handle, bool is_alpha_blend, bool has_transparent_shadows)
ShadowPunctual(ShadowPunctual &&other)
ShadowPunctual(ShadowModule &module)
void release_excess_tilemaps(const Light &light)
#define SHADOW_TILEMAP_RES
#define SHADOW_PAGE_RES
#define SHADOW_MAX_TILEMAP
#define SHADOW_TILEMAP_PER_ROW
#define SHADOW_VIEW_MAX
#define SHADOW_TILEDATA_PER_TILEMAP
#define SHADOW_ATLAS_TEX_SLOT
#define SHADOW_TILEMAPS_TEX_SLOT
SHADOW_TILEMAP_RES tiles_buf[] statistics_buf render_view_buf[SHADOW_VIEW_MAX] GPU_R32UI
PassType
detail::Pass< command::DrawCommandBuf > PassSimple
detail::Pass< command::DrawMultiBuf > PassMain
StorageArrayBuffer< ObjectBounds, 128 > ObjectBoundsBuf
Definition draw_view.hh:30
StorageArrayBuffer< ObjectInfos, 128 > ObjectInfosBuf
Definition draw_view.hh:31
draw::StorageBuffer< ShadowPagesInfoData > ShadowPagesInfoDataBuf
static constexpr const float shadow_face_mat[6][3][3]
draw::StorageArrayBuffer< ShadowTileDataPacked, SHADOW_MAX_TILE, true > ShadowTileDataBuf
draw::StorageArrayBuffer< ShadowTileMapClip, SHADOW_MAX_TILEMAP, true > ShadowTileMapClipBuf
draw::StorageBuffer< DrawCommand, true > DrawIndirectBuf
draw::StorageArrayBuffer< uint2, SHADOW_MAX_PAGE, true > ShadowPageCacheBuf
draw::StorageArrayBuffer< ShadowRenderView, SHADOW_VIEW_MAX, true > ShadowRenderViewBuf
draw::StorageVectorBuffer< ShadowTileMapData, SHADOW_MAX_TILEMAP > ShadowTileMapDataBuf
static constexpr const float shadow_clipmap_scale_mat[4][4]
draw::StorageBuffer< DispatchCommand > DispatchIndirectBuf
draw::StorageVectorBuffer< uint, SHADOW_MAX_PAGE > ShadowPageHeapBuf
VecBase< uint32_t, 2 > uint2
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 2 > int2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
blender::draw::overlay::Instance Instance
static struct PyModuleDef module
Definition python.cpp:991
__int64 int64_t
Definition stdint.h:89
ShadowTileMapDataBuf tilemaps_data
ShadowTileMapDataBuf tilemaps_unused
void release(Span< ShadowTileMap * > free_list)
ShadowTileMapClipBuf tilemaps_clip
void end_sync(ShadowModule &module)
Pool< ShadowTileMap > tilemap_pool
static constexpr int64_t maps_per_row
void sync_orthographic(const float4x4 &object_mat_, int2 origin_offset, int clipmap_level, eShadowProjectionType projection_type_, uint2 shadow_set_membership_=~uint2(0))
static constexpr int64_t tile_map_resolution
static constexpr int64_t tiles_count
ShadowTileMap(int tiles_index_)
void sync_cubeface(eLightType light_type_, const float4x4 &object_mat, float near, float far, eCubeFace face, uint2 shadow_set_membership_=~uint2(0))