33 short blender_area_type,
34 bool use_soft_falloff)
36 switch (blender_light_type) {
80 this->object_to_world = object_to_world;
85 const bool diffuse_visibility = (visibility_flag &
OB_HIDE_DIFFUSE) == 0;
86 const bool glossy_visibility = (visibility_flag &
OB_HIDE_GLOSSY) == 0;
90 float shape_power = shape_radiance_get();
91 float point_power = point_radiance_get();
98 this->lod_min = shadow_lod_min_get(la);
99 this->filter_radius = la->shadow_filter_radius;
122float Light::shadow_lod_min_get(const ::Light *la)
125 float max_res_unit = la->shadow_maximum_resolution;
150 else if (this->
punctual ==
nullptr) {
155float Light::attenuation_radius_get(const ::Light *la,
float light_threshold,
float light_power)
163 return sqrtf(light_power / light_threshold);
166void Light::shape_parameters_set(const ::Light *la,
169 const float threshold,
170 const bool use_jitter)
177 const float surface_max_power =
max(la->diff_fac, la->spec_fac) * max_power;
178 const float volume_max_power = la->volume_fac * max_power;
180 float influence_radius_surface = attenuation_radius_get(la, threshold, surface_max_power);
181 float influence_radius_volume = attenuation_radius_get(la, threshold, volume_max_power);
183 this->local.influence_radius_max =
max(influence_radius_surface, influence_radius_volume);
184 this->local.influence_radius_invsqr_surface =
safe_rcp(
square(influence_radius_surface));
185 this->local.influence_radius_invsqr_volume =
safe_rcp(
square(influence_radius_volume));
187 this->clip_far =
float_as_int(this->local.influence_radius_max);
188 this->clip_near =
float_as_int(this->local.influence_radius_max / 4000.0f);
192 la->shadow_jitter_overblur / 100.0f :
196 float sun_half_angle =
min_ff(la->sun_angle,
DEG2RADF(179.9f)) / 2.0f;
198 this->sun.shadow_angle = sun_half_angle * trace_scaling_fac;
200 this->sun.shadow_angle = (sun_half_angle > 0.0f) ?
max_ff(1e-8f, sun.shadow_angle) : 0.0f;
202 this->sun.shape_radius =
clamp(
tanf(sun_half_angle), 0.001f, 20.0f);
204 this->sun.direction = z_axis;
208 this->area.size =
float2(la->area_size, is_irregular ? la->area_sizey : la->area_size);
210 this->area.size *=
scale.xy() / 2.0f;
211 this->area.shadow_scale = trace_scaling_fac;
212 this->local.shadow_radius =
length(this->area.size) * trace_scaling_fac;
214 this->local.shadow_position =
float3(0.0f);
216 if (this->area.size.x * this->area.size.y < 0.00001f) {
218 this->local.influence_radius_max = 0.0f;
221 this->area.size =
max(
float2(0.003f), this->area.size);
223 this->local.shape_radius =
max(0.001f,
length(this->area.size) / 2.0f);
228 const float spot_size =
cosf(la->spotsize * 0.5f);
229 const float spot_blend = (1.0f - spot_size) * la->spotblend;
231 this->spot.spot_mul = 1.0f /
max(1e-8f, spot_blend);
232 this->spot.spot_bias = -spot_size * this->spot.spot_mul;
233 this->spot.spot_tan =
tanf(
min(la->spotsize * 0.5f,
float(
M_PI_2 - 0.0001f)));
238 this->spot.spot_size_inv =
float2(1.0f);
239 this->spot.spot_mul = 0.0f;
240 this->spot.spot_bias = 1.0f;
241 this->spot.spot_tan = 0.0f;
244 this->local.shadow_radius =
max(0.0f, la->radius) * trace_scaling_fac;
246 this->local.shadow_radius = (la->radius > 0.0f) ?
max_ff(1e-8f, local.shadow_radius) : 0.0f;
248 this->local.shadow_position =
float3(0.0f);
249 this->local.shape_radius = la->radius;
251 this->local.shape_radius =
max(0.001f, this->local.shape_radius);
255float Light::shape_radiance_get()
257 using namespace blender::math;
260 switch (this->
type) {
264 float area = this->area.size.x * this->area.size.y * 4.0f;
283 float inv_sin_sq = 1.0f + 1.0f /
square(this->sun.shape_radius);
292float Light::point_radiance_get()
295 switch (this->
type) {
300 float area = this->area.size.x * this->area.size.y * 4.0f;
303 float mrp_scaling = tmp + (1.0f - tmp) *
M_1_PI;
323void Light::debug_draw()
327 local.influence_radius_max,
328 float4(0.8f, 0.3f, 0.0f, 1.0f));
341 for (
Light &light : light_map_.values()) {
342 light.shadow_discard_safe(inst_.shadows);
348 use_scene_lights_ = inst_.use_scene_lights();
351 use_sun_lights_ = (inst_.world.has_volume_absorption() ==
false);
356 for (
Light &light : light_map_.values()) {
358 light.initialized =
false;
364 local_lights_len_ = 0;
366 if (use_sun_lights_ && inst_.world.sun_threshold() > 0.0f) {
369 ::Light la = blender::dna::shallow_copy(
373 la.
r = la.
g = la.
b = -1.0f;
382 Light &light = light_map_.lookup_or_add_default(world_sunlight_key);
386 sun_lights_len_ += 1;
392 const ::Light *la =
static_cast<const ::
Light *
>(ob->
data);
393 if (use_scene_lights_ ==
false) {
397 if (use_sun_lights_ ==
false) {
407 light.
sync(inst_.shadows,
408 ob->object_to_world(),
422 light_buf_.resize(lights_allocated);
426 int sun_lights_idx = 0;
427 int local_lights_idx = sun_lights_len_;
430 auto it_end = light_map_.items().end();
431 for (
auto it = light_map_.items().begin(); it != it_end; ++it) {
432 Light &light = (*it).value;
434 if (!light.
used && !inst_.is_baking()) {
435 light_map_.remove(it);
439 int dst_idx =
is_sun_light(light.type) ? sun_lights_idx++ : local_lights_idx++;
441 light_buf_[dst_idx] = light;
447 light_buf_.push_update();
453 inst_.info_append_i18n(
"Error: Too many lights in the scene.");
455 lights_len_ = sun_lights_len_ + local_lights_len_;
459 culling_key_buf_.resize(lights_allocated);
460 culling_zdist_buf_.resize(lights_allocated);
461 culling_light_buf_.resize(lights_allocated);
465 int2 render_extent = inst_.film.render_extent_get();
466 int2 probe_extent =
int2(inst_.sphere_probes.probe_render_extent());
474 bool tile_size_valid =
false;
478 uint tile_count = tiles_extent.x * tiles_extent.y;
479 if (tile_count > max_tile_count_threshold) {
482 total_word_count_ = tile_count * word_per_tile;
483 tile_size_valid =
true;
485 }
while (total_word_count_ > max_word_count_threshold || !tile_size_valid);
489 culling_data_buf_.tile_word_len = word_per_tile;
490 culling_data_buf_.tile_size = tile_size;
491 culling_data_buf_.tile_x_len = tiles_extent.x;
492 culling_data_buf_.tile_y_len = tiles_extent.y;
493 culling_data_buf_.items_count = lights_len_;
494 culling_data_buf_.local_lights_len = local_lights_len_;
495 culling_data_buf_.sun_lights_len = sun_lights_len_;
497 culling_tile_buf_.resize(total_word_count_);
504void LightModule::culling_pass_sync()
506 uint safe_lights_len =
max_ii(lights_len_, 1);
515 auto &sub = culling_ps_.
sub(
"Select");
518 sub.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
519 sub.bind_ssbo(
"in_light_buf", light_buf_);
520 sub.bind_ssbo(
"out_light_buf", culling_light_buf_);
521 sub.bind_ssbo(
"out_zdist_buf", culling_zdist_buf_);
522 sub.bind_ssbo(
"out_key_buf", culling_key_buf_);
523 sub.dispatch(
int3(culling_select_dispatch_size, 1, 1));
527 auto &sub = culling_ps_.
sub(
"Sort");
529 sub.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
530 sub.bind_ssbo(
"in_light_buf", light_buf_);
531 sub.bind_ssbo(
"out_light_buf", culling_light_buf_);
532 sub.bind_ssbo(
"in_zdist_buf", culling_zdist_buf_);
533 sub.bind_ssbo(
"in_key_buf", culling_key_buf_);
534 sub.dispatch(
int3(culling_sort_dispatch_size, 1, 1));
538 auto &sub = culling_ps_.
sub(
"Zbin");
540 sub.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
541 sub.bind_ssbo(
"light_buf", culling_light_buf_);
542 sub.bind_ssbo(
"out_zbin_buf", culling_zbin_buf_);
543 sub.dispatch(
int3(1, 1, 1));
547 auto &sub = culling_ps_.sub(
"Tiles");
549 sub.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
550 sub.bind_ssbo(
"light_buf", culling_light_buf_);
551 sub.bind_ssbo(
"out_light_tile_buf", culling_tile_buf_);
552 sub.dispatch(
int3(culling_tile_dispatch_size, 1, 1));
557void LightModule::update_pass_sync()
561 uint safe_lights_len =
max_ii(lights_len_, 1);
564 auto &pass = update_ps_;
567 pass.bind_ssbo(
"light_buf", &culling_light_buf_);
568 pass.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
569 pass.bind_ssbo(
"tilemaps_buf", &inst_.shadows.tilemap_pool.tilemaps_data);
570 pass.bind_ssbo(
"tilemaps_clip_buf", &inst_.shadows.tilemap_pool.tilemaps_clip);
571 pass.bind_resources(inst_.uniform_data);
572 pass.bind_resources(inst_.sampling);
573 pass.dispatch(
int3(shadow_setup_dispatch_size, 1, 1));
577void LightModule::debug_pass_sync()
580 debug_draw_ps_.init();
583 debug_draw_ps_.bind_resources(inst_.uniform_data);
584 debug_draw_ps_.bind_resources(inst_.hiz_buffer.front);
585 debug_draw_ps_.bind_ssbo(
"light_buf", &culling_light_buf_);
586 debug_draw_ps_.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
587 debug_draw_ps_.bind_ssbo(
"light_zbin_buf", &culling_zbin_buf_);
588 debug_draw_ps_.bind_ssbo(
"light_tile_buf", &culling_tile_buf_);
589 debug_draw_ps_.bind_texture(
"depth_tx", &inst_.render_buffers.depth_tx);
596 float far_z =
view.far_clip();
597 float near_z =
view.near_clip();
600 culling_data_buf_.zbin_bias = -near_z * culling_data_buf_.zbin_scale;
601 culling_data_buf_.tile_to_uv_fac = (culling_data_buf_.tile_size /
float2(extent));
602 culling_data_buf_.visible_count = 0;
603 culling_data_buf_.view_is_flipped =
view.is_inverted();
604 culling_data_buf_.push_update();
606 inst_.manager->submit(culling_ps_,
view);
607 inst_.manager->submit(update_ps_,
view);
613 inst_.info_append(
"Debug Mode: Light Culling Validation");
614 inst_.hiz_buffer.update();
616 inst_.manager->submit(debug_draw_ps_,
view);
#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 float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE int float_as_int(float f)
MINLINE void negate_v3(float r[3])
#define SET_FLAG_FROM_TEST(value, test, flag)
const void * DNA_default_table[SDNA_TYPE_MAX]
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
@ GPU_BARRIER_SHADER_STORAGE
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
PassBase< DrawCommandBufType > & sub(const char *name)
void sync_light(const Object *ob, ObjectHandle &handle)
void set_view(View &view, const int2 extent)
void debug_draw(View &view, GPUFrameBuffer *view_fb)
GPUShader * static_shader_get(eShaderType shader_type)
const ShadowSceneData & get_data()
float global_lod_bias() const
Pool< ShadowDirectional > directional_pool
Pool< ShadowPunctual > punctual_pool
UniformBuffer< LightData > sunlight
Simple API to draw debug shapes and log in the viewport.
#define drw_debug_sphere(...)
#define CULLING_SELECT_GROUP_SIZE
#define CULLING_SORT_GROUP_SIZE
#define CULLING_TILE_GROUP_SIZE
#define SHADOW_MAP_MAX_RES
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define CULLING_ZBIN_COUNT
ccl_device_inline float2 power(float2 v, float e)
static bool is_area_light(eLightType type)
static uint2 uint64_to_uint2(uint64_t data)
static bool is_sun_light(eLightType type)
static bool is_spot_light(eLightType type)
static eLightType to_light_type(short blender_light_type, short blender_area_type, bool use_soft_falloff)
static bool is_local_light(eLightType type)
static bool is_point_light(eLightType type)
static float3 transform_location(Transform t)
T clamp(const T &a, const T &min, const T &max)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
T reduce_max(const VecBase< T, Size > &a)
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
MatBase< T, NumCol, NumRow > normalize_and_get_size(const MatBase< T, NumCol, NumRow > &a, VectorT &r_size)
T max(const T &a, const T &b)
VecBase< uint32_t, 2 > uint2
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
VecBase< float, 3 > float3
unsigned __int64 uint64_t
uint64_t light_set_membership
uint64_t shadow_set_membership
LightLinkingRuntime runtime
float shadow_filter_radius
float shadow_jitter_overblur
float shadow_maximum_resolution
LightLinking * light_linking
const MatView< T, ViewNumCol, ViewNumRow, NumCol, NumRow, SrcStartCol, SrcStartRow, Alignment > view() const
static MatBase identity()
void shadow_discard_safe(ShadowModule &shadows)
ShadowDirectional * directional
void shadow_ensure(ShadowModule &shadows)
void sync(ShadowModule &shadows, float4x4 object_to_world, char visibility_flag, const ::Light *la, const LightLinking *light_linking, float threshold)
ShadowPunctual * punctual