36 short blender_area_type,
37 bool use_soft_falloff)
39 switch (blender_light_type) {
86 this->object_to_world = object_to_world;
91 const bool diffuse_visibility = (visibility_flag &
OB_HIDE_DIFFUSE) == 0;
92 const bool glossy_visibility = (visibility_flag &
OB_HIDE_GLOSSY) == 0;
96 float shape_power = shape_radiance_get();
97 float point_power = point_radiance_get();
104 this->lod_min = shadow_lod_min_get(la);
105 this->filter_radius = la->shadow_filter_radius;
128float Light::shadow_lod_min_get(const ::Light *la)
131 float max_res_unit = la->shadow_maximum_resolution;
156 else if (this->
punctual ==
nullptr) {
161float Light::attenuation_radius_get(const ::Light *la,
float light_threshold,
float light_power)
169 return sqrtf(light_power / light_threshold);
172void Light::shape_parameters_set(const ::Light *la,
175 const float threshold,
176 const bool use_jitter)
184 const float surface_max_power =
max(la->diff_fac, la->spec_fac) * max_power;
185 const float volume_max_power = la->volume_fac * max_power;
187 float influence_radius_surface = attenuation_radius_get(la, threshold, surface_max_power);
188 float influence_radius_volume = attenuation_radius_get(la, threshold, volume_max_power);
190 this->local.influence_radius_max =
max(influence_radius_surface, influence_radius_volume);
191 this->local.influence_radius_invsqr_surface =
safe_rcp(
square(influence_radius_surface));
192 this->local.influence_radius_invsqr_volume =
safe_rcp(
square(influence_radius_volume));
194 this->clip_far =
float_as_int(this->local.influence_radius_max);
195 this->clip_near =
float_as_int(this->local.influence_radius_max / 4000.0f);
199 la->shadow_jitter_overblur / 100.0f :
203 float sun_half_angle =
min_ff(la->sun_angle,
DEG2RADF(179.9f)) / 2.0f;
205 this->sun.shadow_angle = sun_half_angle * trace_scaling_fac;
207 this->sun.shadow_angle = (sun_half_angle > 0.0f) ?
max_ff(1e-8f, sun.shadow_angle) : 0.0f;
209 this->sun.shape_radius =
clamp(
tanf(sun_half_angle), 0.001f, 20.0f);
211 this->sun.direction = z_axis;
215 this->
area.size =
float2(la->area_size, is_irregular ? la->area_sizey : la->area_size);
218 this->
area.shadow_scale = trace_scaling_fac;
219 this->local.shadow_radius =
length(this->
area.size) * trace_scaling_fac;
221 this->local.shadow_position =
float3(0.0f);
223 if (this->
area.size.x * this->area.size.y < 0.00001f) {
225 this->local.influence_radius_max = 0.0f;
230 this->local.shape_radius =
max(0.001f,
length(this->
area.size) / 2.0f);
235 const float spot_size =
cosf(la->spotsize * 0.5f);
236 const float spot_blend = (1.0f - spot_size) * la->spotblend;
238 this->spot.spot_mul = 1.0f /
max(1e-8f, spot_blend);
239 this->spot.spot_bias = -spot_size * this->spot.spot_mul;
240 this->spot.spot_tan =
tanf(
min(la->spotsize * 0.5f,
float(
M_PI_2 - 0.0001f)));
245 this->spot.spot_size_inv =
float2(1.0f);
246 this->spot.spot_mul = 0.0f;
247 this->spot.spot_bias = 1.0f;
248 this->spot.spot_tan = 0.0f;
251 this->local.shadow_radius =
max(0.0f, la->radius) * trace_scaling_fac;
253 this->local.shadow_radius = (la->radius > 0.0f) ?
max_ff(1e-8f, local.shadow_radius) : 0.0f;
255 this->local.shadow_position =
float3(0.0f);
256 this->local.shape_radius = la->radius;
258 this->local.shape_radius =
max(0.001f, this->local.shape_radius);
262float Light::shape_radiance_get()
264 using namespace blender::math;
267 switch (this->
type) {
271 float area = this->
area.size.x * this->
area.size.y * 4.0f;
290 float inv_sin_sq = 1.0f + 1.0f /
square(this->sun.shape_radius);
299float Light::point_radiance_get()
302 switch (this->
type) {
307 float area = this->
area.size.x * this->
area.size.y * 4.0f;
310 float mrp_scaling = tmp + (1.0f - tmp) *
M_1_PI;
330void Light::debug_draw()
333 local.influence_radius_max,
334 float4(0.8f, 0.3f, 0.0f, 1.0f));
346 for (
Light &light : light_map_.values()) {
347 light.shadow_discard_safe(inst_.shadows);
354 if (inst_.is_viewport()) {
356 inst_.sampling.reset();
362 use_sun_lights_ = (inst_.world.has_volume_absorption() ==
false);
367 for (
Light &light : light_map_.values()) {
369 light.initialized =
false;
375 local_lights_len_ = 0;
377 if (use_sun_lights_ && inst_.world.sun_threshold() > 0.0f) {
380 ::Light la = blender::dna::shallow_copy(
384 la.
r = la.
g = la.
b = -1.0f;
393 Light &light = light_map_.lookup_or_add_default(world_sunlight_key);
397 sun_lights_len_ += 1;
404 if (use_scene_lights_ ==
false) {
408 if (use_sun_lights_ ==
false) {
418 light.
sync(inst_.shadows,
419 ob->object_to_world(),
433 light_buf_.resize(lights_allocated);
437 int sun_lights_idx = 0;
438 int local_lights_idx = sun_lights_len_;
441 auto it_end = light_map_.items().end();
442 for (
auto it = light_map_.items().begin(); it != it_end; ++it) {
443 Light &light = (*it).value;
445 if (!light.
used && !inst_.is_baking()) {
446 light_map_.remove(it);
450 int dst_idx =
is_sun_light(light.type) ? sun_lights_idx++ : local_lights_idx++;
452 light_buf_[dst_idx] = light;
458 light_buf_.push_update();
464 inst_.info_append_i18n(
"Error: Too many lights in the scene.");
466 lights_len_ = sun_lights_len_ + local_lights_len_;
470 culling_key_buf_.resize(lights_allocated);
471 culling_zdist_buf_.resize(lights_allocated);
472 culling_light_buf_.resize(lights_allocated);
476 int2 render_extent = inst_.film.render_extent_get();
477 int2 probe_extent =
int2(inst_.sphere_probes.probe_render_extent());
485 bool tile_size_valid =
false;
489 uint tile_count = tiles_extent.x * tiles_extent.y;
490 if (tile_count > max_tile_count_threshold) {
493 total_word_count_ = tile_count * word_per_tile;
494 tile_size_valid =
true;
496 }
while (total_word_count_ > max_word_count_threshold || !tile_size_valid);
500 culling_data_buf_.tile_word_len = word_per_tile;
501 culling_data_buf_.tile_size = tile_size;
502 culling_data_buf_.tile_x_len = tiles_extent.x;
503 culling_data_buf_.tile_y_len = tiles_extent.y;
504 culling_data_buf_.items_count = lights_len_;
505 culling_data_buf_.local_lights_len = local_lights_len_;
506 culling_data_buf_.sun_lights_len = sun_lights_len_;
508 culling_tile_buf_.resize(total_word_count_);
515void LightModule::culling_pass_sync()
517 uint safe_lights_len =
max_ii(lights_len_, 1);
526 auto &sub = culling_ps_.
sub(
"Select");
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(
"out_zdist_buf", culling_zdist_buf_);
533 sub.bind_ssbo(
"out_key_buf", culling_key_buf_);
534 sub.dispatch(
int3(culling_select_dispatch_size, 1, 1));
538 auto &sub = culling_ps_.
sub(
"Sort");
540 sub.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
541 sub.bind_ssbo(
"in_light_buf", light_buf_);
542 sub.bind_ssbo(
"out_light_buf", culling_light_buf_);
543 sub.bind_ssbo(
"in_zdist_buf", culling_zdist_buf_);
544 sub.bind_ssbo(
"in_key_buf", culling_key_buf_);
545 sub.dispatch(
int3(culling_sort_dispatch_size, 1, 1));
549 auto &sub = culling_ps_.
sub(
"Zbin");
551 sub.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
552 sub.bind_ssbo(
"light_buf", culling_light_buf_);
553 sub.bind_ssbo(
"out_zbin_buf", culling_zbin_buf_);
554 sub.dispatch(
int3(1, 1, 1));
558 auto &sub = culling_ps_.sub(
"Tiles");
560 sub.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
561 sub.bind_ssbo(
"light_buf", culling_light_buf_);
562 sub.bind_ssbo(
"out_light_tile_buf", culling_tile_buf_);
563 sub.dispatch(
int3(culling_tile_dispatch_size, 1, 1));
568void LightModule::update_pass_sync()
572 uint safe_lights_len =
max_ii(lights_len_, 1);
575 auto &pass = update_ps_;
578 pass.bind_ssbo(
"light_buf", &culling_light_buf_);
579 pass.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
580 pass.bind_ssbo(
"tilemaps_buf", &inst_.shadows.tilemap_pool.tilemaps_data);
581 pass.bind_ssbo(
"tilemaps_clip_buf", &inst_.shadows.tilemap_pool.tilemaps_clip);
582 pass.bind_resources(inst_.uniform_data);
583 pass.bind_resources(inst_.sampling);
584 pass.dispatch(
int3(shadow_setup_dispatch_size, 1, 1));
588void LightModule::debug_pass_sync()
591 debug_draw_ps_.init();
594 debug_draw_ps_.bind_resources(inst_.uniform_data);
595 debug_draw_ps_.bind_resources(inst_.hiz_buffer.front);
596 debug_draw_ps_.bind_ssbo(
"light_buf", &culling_light_buf_);
597 debug_draw_ps_.bind_ssbo(
"light_cull_buf", &culling_data_buf_);
598 debug_draw_ps_.bind_ssbo(
"light_zbin_buf", &culling_zbin_buf_);
599 debug_draw_ps_.bind_ssbo(
"light_tile_buf", &culling_tile_buf_);
600 debug_draw_ps_.bind_texture(
"depth_tx", &inst_.render_buffers.depth_tx);
607 float far_z =
view.far_clip();
608 float near_z =
view.near_clip();
611 culling_data_buf_.zbin_bias = -near_z * culling_data_buf_.zbin_scale;
612 culling_data_buf_.tile_to_uv_fac = (culling_data_buf_.tile_size /
float2(extent));
613 culling_data_buf_.visible_count = 0;
614 culling_data_buf_.view_is_flipped =
view.is_inverted();
615 culling_data_buf_.push_update();
617 inst_.manager->submit(culling_ps_,
view);
618 inst_.manager->submit(update_ps_,
view);
624 inst_.info_append(
"Debug Mode: Light Culling Validation");
625 inst_.hiz_buffer.update();
627 inst_.manager->submit(debug_draw_ps_,
view);
General operations, lookup, etc. for blender lights.
blender::float3 BKE_light_color(const Light &light)
float BKE_light_area(const Light &light, const blender::float4x4 &object_to_world)
float BKE_light_power(const Light &light)
#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]
T & DRW_object_get_data_for_drawing(const Object &object)
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
@ GPU_BARRIER_SHADER_STORAGE
BMesh const char void * data
unsigned long long int uint64_t
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, gpu::FrameBuffer *view_fb)
gpu::Shader * 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 CULLING_SELECT_GROUP_SIZE
#define CULLING_SORT_GROUP_SIZE
#define CULLING_TILE_GROUP_SIZE
#define SHADOW_MAP_MAX_RES
#define CULLING_ZBIN_COUNT
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
ccl_device_inline float2 power(const float2 v, const float e)
void drw_debug_sphere(const float3 center, float radius, const float4 color, const uint lifetime)
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)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &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
uint64_t light_set_membership
uint64_t shadow_set_membership
LightLinkingRuntime runtime
float shadow_filter_radius
float shadow_jitter_overblur
float area(const Transform &tfm) const
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