35 uint2 shadow_set_membership_)
43 level = clipmap_level;
78 uint2 shadow_set_membership_)
124 const float4 debug_color[6] = {
125 {1.0f, 0.1f, 0.1f, 1.0f},
126 {0.1f, 1.0f, 0.1f, 1.0f},
127 {0.0f, 0.2f, 1.0f, 1.0f},
128 {1.0f, 1.0f, 0.3f, 1.0f},
129 {0.1f, 0.1f, 0.1f, 1.0f},
130 {1.0f, 1.0f, 1.0f, 1.0f},
132 float4 color = debug_color
194 module.do_full_update_ = true;
199 if (newly_unused_count > 0) {
203 for (
uint index : newly_unused_indices) {
230 if (tilemaps_.size() <= tilemaps_needed) {
233 auto span = tilemaps_.as_span();
235 tilemaps_ = span.take_front(tilemaps_needed);
242 float4x4 object_to_world = light.object_to_world;
246 while (tilemaps_.size() < tilemaps_needed) {
247 tilemaps_.append(tilemap_pool.
acquire());
252 for (
int i : tilemaps_.index_range()) {
254 tilemaps_[face]->sync_cubeface(
255 light.type, object_to_world, near, far, face, light.shadow_set_membership);
258 light.local.tilemaps_count = tilemaps_needed;
263 tilemap->set_updated();
296void ShadowDirectional::cascade_tilemaps_distribution_near_far_points(
const Camera &camera,
301 const CameraData &cam_data = camera.data_get();
304 light.object_to_world, camera.position() - camera.forward() * cam_data.clip_far);
306 light.object_to_world, camera.position() - camera.forward() * cam_data.clip_near);
309IndexRange ShadowDirectional::cascade_level_range(
const Light &light,
const Camera &camera)
317 const int max_tilemap_per_shadows = 16;
318 const CameraData &cam_data = camera.data_get();
320 float3 near_point, far_point;
321 cascade_tilemaps_distribution_near_far_points(camera, light, near_point, far_point);
325 float depth_range_in_shadow_space =
distance(far_point.xy(), near_point.xy());
326 float min_depth_tilemap_size = 2 * (depth_range_in_shadow_space / max_tilemap_per_shadows);
329 float min_diagonal_tilemap_size = cam_data.screen_diagonal_length;
331 if (camera.is_perspective()) {
333 min_diagonal_tilemap_size *= cam_data.clip_far / cam_data.clip_near;
338 int lod_level =
ceil(
log2(
max_ff(min_depth_tilemap_size, min_diagonal_tilemap_size)) + 0.5);
344 int tilemap_len =
ceil(0.5f + depth_range_in_shadow_space / per_tilemap_coverage);
348void ShadowDirectional::cascade_tilemaps_distribution(
Light &light,
const Camera &camera)
352 float4x4 object_mat = light.object_to_world;
359 float3 near_point, far_point;
360 cascade_tilemaps_distribution_near_far_points(camera, light, near_point, far_point);
362 float2 local_view_direction =
normalize(far_point.xy() - near_point.xy());
363 float2 farthest_tilemap_center = local_view_direction * half_size * (levels_range.
size() - 1);
366 light.object_to_world.x.w = near_point.
x;
367 light.object_to_world.y.w = near_point.
y;
368 light.object_to_world.z.w = near_point.
z;
373 int2 offset_vector =
int2(
round(farthest_tilemap_center / tile_size));
375 light.sun.clipmap_base_offset_neg =
int2(0);
376 light.sun.clipmap_base_offset_pos = (offset_vector * (1 << 16)) /
380 int level = levels_range.
first();
382 ShadowTileMap *tilemap = tilemaps_[i];
385 int2 level_offset = origin_offset +
387 tilemap->sync_orthographic(
392 tilemap->set_updated();
395 light.sun.clipmap_origin =
float2(origin_offset) * tile_size;
401 light.sun.clipmap_lod_min = levels_range.
first();
402 light.sun.clipmap_lod_max = levels_range.
last();
416 int max_level =
ceil(
log2(cam.bound_radius() +
distance(cam.bound_center(), cam.position())));
418 max_level =
max(min_level, max_level) + 1;
422 const int max_tilemap_per_shadows = 24;
424 range =
range.take_back(max_tilemap_per_shadows);
429void ShadowDirectional::clipmap_tilemaps_distribution(
Light &light,
const Camera &camera)
431 float4x4 object_mat = light.object_to_world;
435 ShadowTileMap *tilemap = tilemaps_[lod];
437 int level = levels_range.
first() + lod;
442 float2 light_space_camera_position = camera.position() *
float2x3(object_mat.
view<2, 3>());
445 tilemap->sync_orthographic(
450 tilemap->set_updated();
461 int2 lvl_offset_next = tilemaps_[lod + 1]->grid_offset;
462 int2 lvl_offset = tilemaps_[lod]->grid_offset;
463 int2 lvl_delta = lvl_offset - (lvl_offset_next * 2);
470 light.sun.clipmap_base_offset_pos = pos_offset;
471 light.sun.clipmap_base_offset_neg = neg_offset;
474 int2 level_offset_max = tilemaps_[levels_range.
size() - 1]->grid_offset;
481 light.object_to_world.x.w = location.
x;
482 light.object_to_world.y.w = location.
y;
483 light.object_to_world.z.w = location.
z;
485 light.sun.clipmap_origin =
float2(level_offset_max * tile_size_max);
487 light.sun.clipmap_lod_min = levels_range.
first();
488 light.sun.clipmap_lod_max = levels_range.
last();
494 cascade_level_range(light, camera) :
495 clipmap_level_range(camera);
497 if (levels_range == levels_new) {
506 auto span = tilemaps_.as_span();
509 tilemaps_ = span.slice(isect_range.
shift(-levels_range.
start()));
510 levels_range = isect_range;
517 cascade_level_range(light, camera) :
518 clipmap_level_range(camera);
520 if (levels_range != levels_new) {
528 for (
int64_t i = 0; i < before_range; i++) {
529 tilemaps_.append(tilemap_pool.
acquire());
532 tilemaps_.extend(cached_tilemaps);
533 for (
int64_t i = 0; i < after_range; i++) {
534 tilemaps_.append(tilemap_pool.
acquire());
536 levels_range = levels_new;
540 light.clip_near = 0x7F7FFFFF;
541 light.clip_far = int(0xFF7FFFFFu ^ 0x7FFFFFFFu);
544 cascade_tilemaps_distribution(light, camera);
547 clipmap_tilemaps_distribution(light, camera);
560 for (
int i = 0; i < statistics_buf_.size(); i++) {
562 statistics_buf_.current().clear_to_zero();
563 statistics_buf_.swap();
576 if (is_metal_backend && is_tile_based_arch) {
589 bool update_lights =
false;
591 bool use_jitter = enable_shadow &&
599 for (
Light &light : inst_.
lights.light_map_.values()) {
600 light.initialized =
false;
609 const size_t page_byte_size =
square_i(shadow_page_size_) *
sizeof(int);
610 shadow_page_len_ = int(
divide_ceil_ul(pool_byte_size, page_byte_size));
620 if (atlas_tx_.
ensure_2d_array(atlas_type, atlas_extent, atlas_layers, tex_usage)) {
622 do_full_update_ =
true;
629 "Error: Could not allocate shadow atlas. Most likely out of GPU memory.");
636 for (
int i = 0; i < statistics_buf_.size(); i++) {
637 statistics_buf_.swap();
641 statistics_buf_.swap();
643 statistics_buf_.current().read();
648 "Error: Shadow buffer full, may result in missing shadows and lower "
649 "performance. ({} / {})",
654 inst_.
info_append_i18n(
"Error: Too many shadow updates, some shadows might be incorrect.");
662 for (
int i = 0; i < multi_viewports_.size(); i++) {
666 multi_viewports_[i][0] = 0;
667 multi_viewports_[i][1] = 0;
668 multi_viewports_[i][2] = size_in_tile * shadow_page_size_;
669 multi_viewports_[i][3] = size_in_tile * shadow_page_size_;
675 past_casters_updated_.
clear();
676 curr_casters_updated_.
clear();
677 curr_casters_.
clear();
678 jittered_transparent_casters_.
clear();
679 update_casters_ =
true;
681 if (box_batch_ ==
nullptr) {
698 int directional_level = std::max(0,
int(std::ceil(
log2(surfel_coverage_area / texel_size))));
704 sub.
bind_ssbo(
"surfel_buf", &surfels_buf);
705 sub.
bind_ssbo(
"capture_info_buf", &capture_info_buf);
722 sub.
push_constant(
"input_depth_extent", &input_depth_extent_);
726 sub.
dispatch(&dispatch_depth_scan_size_);
740 sub.
push_constant(
"fb_resolution", &usage_tag_fb_resolution_);
746 tilemap_usage_transparent_ps_ = ⊂
755 bool has_transparent_shadows)
758 if (!is_shadow_caster && !is_alpha_blend) {
763 shadow_ob.
used =
true;
765 const bool has_jittered_transparency = has_transparent_shadows && data_.
use_jitter;
766 if (is_shadow_caster && (handle.
recalc || !is_initialized || has_jittered_transparency)) {
767 if (handle.
recalc && is_initialized) {
771 if (has_jittered_transparency) {
772 jittered_transparent_casters_.
append(resource_handle.
raw);
775 curr_casters_updated_.
append(resource_handle.
raw);
780 if (is_shadow_caster) {
781 curr_casters_.
append(resource_handle.
raw);
784 if (is_alpha_blend && !inst_.
is_baking()) {
785 tilemap_usage_transparent_ps_->
draw(box_batch_, resource_handle);
792 for (
Light &light : inst_.
lights.light_map_.values()) {
794 if ((!light.used || !enabled_) && !inst_.
is_baking()) {
795 light.shadow_discard_safe(*
this);
797 else if (light.directional !=
nullptr) {
798 light.directional->release_excess_tilemaps(light, inst_.
camera);
800 else if (light.punctual !=
nullptr) {
801 light.punctual->release_excess_tilemaps(light);
807 for (
Light &light : inst_.
lights.light_map_.values()) {
808 if (enabled_ ==
false) {
811 else if (light.directional !=
nullptr) {
812 light.directional->end_sync(light, inst_.
camera);
814 else if (light.punctual !=
nullptr) {
815 light.punctual->end_sync(light);
824 auto it_end = objects_.items().end();
825 for (
auto it = objects_.items().begin(); it != it_end; ++it) {
835 shadow_ob.
used =
false;
844 if (do_full_update_) {
845 do_full_update_ =
false;
854 pages_free_data_[i] = 0xFFFFFFFFu;
898 sub.
bind_ssbo(
"casters_id_buf", curr_casters_);
915 sub.
bind_ssbo(
"pages_cached_buf", pages_cached_data_);
934 if (past_casters_updated_.
size() > 0) {
936 pass.
bind_ssbo(
"resource_ids_buf", past_casters_updated_);
940 if (curr_casters_updated_.
size() > 0) {
942 pass.
bind_ssbo(
"resource_ids_buf", curr_casters_updated_);
950 PassSimple &pass = jittered_transparent_caster_update_ps_;
952 if (jittered_transparent_casters_.
size() > 0) {
957 pass.
bind_ssbo(
"resource_ids_buf", jittered_transparent_casters_);
989 sub.
push_constant(
"max_view_per_tilemap", &max_view_per_tilemap_);
1001 sub.
bind_ssbo(
"pages_infos_buf", pages_infos_data_);
1002 sub.
bind_ssbo(
"pages_free_buf", pages_free_data_);
1003 sub.
bind_ssbo(
"pages_cached_buf", pages_cached_data_);
1016 sub.
bind_ssbo(
"pages_infos_buf", pages_infos_data_);
1017 sub.
bind_ssbo(
"pages_free_buf", pages_free_data_);
1018 sub.
bind_ssbo(
"pages_cached_buf", pages_cached_data_);
1019 sub.
bind_ssbo(
"statistics_buf", statistics_buf_.current());
1020 sub.
bind_ssbo(
"clear_dispatch_buf", clear_dispatch_buf_);
1021 sub.
bind_ssbo(
"tile_draw_buf", tile_draw_buf_);
1031 sub.
bind_ssbo(
"statistics_buf", statistics_buf_.current());
1032 sub.
bind_ssbo(
"pages_infos_buf", pages_infos_data_);
1033 sub.
bind_ssbo(
"pages_free_buf", pages_free_data_);
1034 sub.
bind_ssbo(
"pages_cached_buf", pages_cached_data_);
1044 sub.
bind_ssbo(
"pages_infos_buf", &pages_infos_data_);
1045 sub.
bind_ssbo(
"statistics_buf", &statistics_buf_.current());
1047 sub.
bind_ssbo(
"render_view_buf", &render_view_buf_);
1058 sub.
bind_ssbo(
"statistics_buf", &statistics_buf_.current());
1059 sub.
bind_ssbo(
"render_view_buf", &render_view_buf_);
1061 sub.
bind_ssbo(
"clear_dispatch_buf", &clear_dispatch_buf_);
1062 sub.
bind_ssbo(
"tile_draw_buf", &tile_draw_buf_);
1063 sub.
bind_ssbo(
"dst_coord_buf", &dst_coord_buf_);
1064 sub.
bind_ssbo(
"src_coord_buf", &src_coord_buf_);
1065 sub.
bind_ssbo(
"render_map_buf", &render_map_buf_);
1088 sub.
bind_ssbo(
"pages_infos_buf", pages_infos_data_);
1089 sub.
bind_ssbo(
"dst_coord_buf", dst_coord_buf_);
1090 sub.
bind_image(
"shadow_atlas_img", atlas_tx_);
1112 debug_draw_ps_.
init();
1115 if (object_active ==
nullptr) {
1121 if (inst_.
lights.light_map_.contains(object_key) ==
false) {
1125 Light &light = inst_.
lights.light_map_.lookup(object_key);
1137 debug_draw_ps_.
push_constant(
"debug_tilemap_index", light.tilemap_index);
1148 bool is_perspective,
1151 float min_dim = float(
min_ii(extent.x, extent.y));
1157 if (is_perspective) {
1164bool ShadowModule::shadow_update_finished(
int loop_count)
1187 statistics_buf_.current().async_flush_to_host();
1188 statistics_buf_.current().read();
1189 ShadowStatistics stats = statistics_buf_.current();
1191 if (stats.page_used_count > shadow_page_len_) {
1193 "Error: Shadow buffer full, may result in missing shadows and lower "
1194 "performance. ({} / {})",
1195 stats.page_used_count,
1203int ShadowModule::max_view_per_tilemap()
1212 int potential_view_count = 0;
1218 potential_view_count += 1;
1224 max_view_count =
math::min(2, max_view_count);
1228 max_view_count =
math::min(1, max_view_count);
1231 return max_view_count;
1234void ShadowModule::ShadowView::compute_visibility(
ObjectBoundsBuf &bounds,
1244 resource_len * word_per_draw;
1273 if (enabled_ ==
false) {
1278 input_depth_extent_ = extent;
1284 max_view_per_tilemap_ = max_view_per_tilemap();
1290 usage_tag_fb.
ensure(usage_tag_fb_resolution_);
1298 shadow_depth_fb_tx_.
free();
1299 shadow_depth_accum_tx_.
free();
1300 render_fb_.
ensure(fb_size);
1328 if (loop_count == 0) {
1336 statistics_buf_.current().async_flush_to_host();
1343 use_flush |= loop_count != 0;
1361 else if (shadow_depth_fb_tx_.
is_valid()) {
1374 reinterpret_cast<int(*)[4]
>(multi_viewports_.data()));
1388 }
while (!shadow_update_finished(loop_count));
1414 inst_.
info_append(
"Debug Mode: Shadow Tile Random Color");
1417 inst_.
info_append(
"Debug Mode: Shadow Tilemap Random Color");
#define BLI_assert_unreachable()
MINLINE uint ceil_to_multiple_u(uint a, uint b)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE uint divide_ceil_u(uint a, uint b)
MINLINE int square_i(int a)
MINLINE int max_ii(int a, int b)
MINLINE uint64_t divide_ceil_ul(uint64_t a, uint64_t b)
MINLINE int clamp_i(int value, int min, int max)
MINLINE float int_as_float(int i)
bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
T * DEG_get_original(T *id)
@ SCE_EEVEE_SHADOW_ENABLED
@ SCE_EEVEE_SHADOW_JITTERED_VIEWPORT
blender::gpu::Batch * GPU_batch_unit_cube() ATTR_WARN_UNUSED_RESULT
@ GPU_STOREACTION_DONT_CARE
void GPU_compute_dispatch(GPUShader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
eGPUBackendType GPU_backend_get_type()
void GPU_debug_group_end()
void GPU_debug_group_begin(const char *name)
void GPU_framebuffer_multi_viewports_set(GPUFrameBuffer *gpu_fb, const int viewport_rects[GPU_MAX_VIEWPORTS][4])
#define GPU_ATTACHMENT_TEXTURE(_texture)
GPUFrameBuffer * GPU_framebuffer_active_get()
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
#define GPU_framebuffer_bind_ex(_fb,...)
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
void GPU_shader_bind(GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
int GPU_shader_get_ssbo_binding(GPUShader *shader, const char *name)
void GPU_memory_barrier(eGPUBarrier barrier)
@ GPU_BARRIER_SHADER_STORAGE
@ GPU_BARRIER_TEXTURE_FETCH
@ GPU_BARRIER_SHADER_IMAGE_ACCESS
void GPU_storagebuf_bind(GPUStorageBuf *ssbo, int slot)
void GPU_storagebuf_clear(GPUStorageBuf *ssbo, uint32_t clear_value)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_MEMORYLESS
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_TEXTURE_USAGE_ATOMIC
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
constexpr int64_t first() const
constexpr int64_t one_after_last() const
constexpr IndexRange shift(int64_t n) const
constexpr IndexRange intersect(IndexRange other) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr int64_t start() const
void append(const T &value)
void reserve(const int64_t min_capacity)
Span< T > as_span() const
void ensure(GPUAttachment depth=GPU_ATTACHMENT_NONE, GPUAttachment color1=GPU_ATTACHMENT_NONE, GPUAttachment color2=GPU_ATTACHMENT_NONE, GPUAttachment color3=GPU_ATTACHMENT_NONE, GPUAttachment color4=GPU_ATTACHMENT_NONE, GPUAttachment color5=GPU_ATTACHMENT_NONE, GPUAttachment color6=GPU_ATTACHMENT_NONE, GPUAttachment color7=GPU_ATTACHMENT_NONE, GPUAttachment color8=GPU_ATTACHMENT_NONE)
SwapChain< ObjectBoundsBuf, 2 > bounds_buf
void submit(PassSimple &pass, View &view)
void resize(int64_t new_size)
void append(const T &value)
void clear(float4 values)
void filter_mode(bool do_filter)
bool ensure_2d_array(eGPUTextureFormat format, int2 extent, int layers, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
bool ensure_2d(eGPUTextureFormat format, int2 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
UniformArrayBuffer< ViewCullingData, DRW_VIEW_MAX > culling_
VisibilityBuf visibility_buf_
void compute_procedural_bounds()
UniformArrayBuffer< ViewMatrices, DRW_VIEW_MAX > data_
UniformArrayBuffer< ViewMatrices, DRW_VIEW_MAX > & matrices_ubo_get()
int visibility_word_per_draw() const
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
void bind_resources(U &resources)
void bind_image(const char *name, GPUTexture *image)
void draw(gpu::Batch *batch, uint instance_len=-1, uint vertex_len=-1, uint vertex_first=-1, ResourceHandleRange handle={0}, uint custom_id=0)
PassBase< DrawCommandBufType > & sub(const char *name)
void dispatch(int group_len)
void barrier(eGPUBarrier type)
void state_set(DRWState state, int clip_plane_count=0)
void framebuffer_set(GPUFrameBuffer **framebuffer)
void state_stencil(uint8_t write_mask, uint8_t reference, uint8_t compare_mask)
void push_constant(const char *name, const float &data)
void draw_procedural(GPUPrimType primitive, uint instance_len, uint vertex_len, uint vertex_first=-1, ResourceHandleRange handle={0}, uint custom_id=0)
void bind_ssbo(const char *name, GPUStorageBuf *buffer)
void shader_set(GPUShader *shader)
bool is_perspective() const
struct blender::eevee::Film::DepthState depth
struct blender::eevee::HiZBuffer::@178 front
A running instance of the engine.
VolumeProbeModule volume_probes
void info_append_i18n(const char *msg, Args &&...args)
const DRWContext * draw_ctx
void info_append(const char *msg, Args &&...args)
UniformDataModule uniform_data
bool finished_viewport() const
GPUShader * static_shader_get(eShaderType shader_type)
static float coverage_get(int lvl)
static float tile_size_get(int lvl)
void end_sync(Light &light, const Camera &camera)
void release_excess_tilemaps(const Light &light, const Camera &camera)
ShadowModule(Instance &inst, ShadowSceneData &data)
ShadowTileMapPool tilemap_pool
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)
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)
void release_excess_tilemaps(const Light &light)
void end_sync(Light &light)
struct blender::eevee::VolumeModule::@180 properties
bool needs_shadow_tagging() const
struct blender::eevee::VolumeModule::@179 result
Simple API to draw debug shapes and log in the viewport.
#define DRW_VISIBILITY_GROUP_SIZE
#define DRW_VIEW_CULLING_UBO_SLOT
#define DRW_OBJ_INFOS_SLOT
#define DRW_VIEW_UBO_SLOT
@ DRW_STATE_WRITE_STENCIL
#define SHADOW_TILEMAP_RES
#define SHADOW_MAX_TILEMAP
#define SHADOW_PAGE_PER_ROW
#define SHADOW_CLIPMAP_GROUP_SIZE
#define SHADOW_DEPTH_SCAN_GROUP_SIZE
#define VOLUME_GROUP_SIZE
#define SHADOW_TILEDATA_PER_TILEMAP
#define SHADOW_BOUNDS_GROUP_SIZE
#define SHADOW_PAGE_PER_COL
#define SHADOW_PAGE_PER_LAYER
#define SHADOW_TILEMAP_LOD
VecBase< float, D > normalize(VecOp< float, D >) RET
void drw_debug_matrix_as_bbox(const float4x4 &mat, const float4 color, const uint lifetime)
StorageArrayBuffer< ObjectBounds, 128 > ObjectBoundsBuf
StorageArrayBuffer< ObjectInfos, 128 > ObjectInfosBuf
@ SHADOW_TILEMAP_TAG_USAGE_SURFELS
@ SHADOW_TILEMAP_RENDERMAP
@ SHADOW_TILEMAP_FINALIZE
@ SHADOW_TILEMAP_TAG_USAGE_OPAQUE
@ SHADOW_TILEMAP_TAG_USAGE_TRANSPARENT
@ SHADOW_TILEMAP_TAG_USAGE_VOLUME
@ SHADOW_TILEMAP_TAG_UPDATE
static constexpr const float shadow_face_mat[6][3][3]
static int2 shadow_cascade_grid_offset(int2 base_offset, int level_relative)
static int light_local_tilemap_count(LightData light)
static float3 transform_direction_transposed(Transform t, float3 direction)
@ DEBUG_SHADOW_TILE_RANDOM_COLOR
@ DEBUG_SHADOW_TILEMAP_RANDOM_COLOR
static uint shadow_page_pack(uint3 page)
@ SHADOW_PROJECTION_CLIPMAP
@ SHADOW_PROJECTION_CASCADE
@ SHADOW_PROJECTION_CUBEFACE
MatBase< T, 4, 4 > orthographic(T left, T right, T bottom, T top, T near_clip, T far_clip)
Create an orthographic projection matrix using OpenGL coordinate convention: Maps each axis range to ...
MatBase< T, 4, 4 > perspective(T left, T right, T bottom, T top, T near_clip, T far_clip)
Create a perspective projection matrix using OpenGL coordinate convention: Maps each axis range to [-...
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
T distance(const T &a, const T &b)
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T min(const T &a, const T &b)
CartesianBasis invert(const CartesianBasis &basis)
VectorT project_point(const MatT &mat, const VectorT &point)
T max(const T &a, const T &b)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
VecBase< uint32_t, 4 > uint4
MatBase< float, 2, 3 > float2x3
bool assign_if_different(T &old_value, T new_value)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
static struct PyModuleDef module
float shadow_resolution_scale
const c_style_mat & ptr() const
const MatView< T, ViewNumCol, ViewNumRow, NumCol, NumRow, SrcStartCol, SrcStartRow, Alignment > view() const
ResourceHandle resource_handle
eShadowProjectionType projection_type
uint2 shadow_set_membership
ShadowTileMapDataBuf tilemaps_data
ShadowTileMapDataBuf tilemaps_unused
ShadowTileDataBuf tiles_data
void release(Span< ShadowTileMap * > free_list)
ShadowTileMapClipBuf tilemaps_clip
void end_sync(ShadowModule &module)
ShadowTileMap * acquire()
Vector< uint > free_indices
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
void sync_cubeface(eLightType light_type_, const float4x4 &object_mat, float near, float far, eCubeFace face, uint2 shadow_set_membership_=~uint2(0))