32 bool use_l2_band =
false;
33 int sh_coef_len = use_l2_band ? 9 : 4;
35 int texel_byte_size = 8;
36 uint atlas_col_count = 0;
37 uint atlas_row_count = 0;
43 irradiance_atlas_tx_.
free();
45 for (
uint irradiance_pool_size = irradiance_pool_size_;
46 irradiance_pool_size >= 16 && !irradiance_atlas_tx_.
is_valid();
47 irradiance_pool_size >>= 1)
49 int atlas_byte_size = 1024 * 1024 * irradiance_pool_size;
51 constexpr uint atlas_col_count_min = 16;
52 constexpr uint atlas_col_count_max = 16384;
53 for (
uint atlas_col_count_try = atlas_col_count_min;
54 atlas_col_count_try <= atlas_col_count_max && !irradiance_atlas_tx_.
is_valid();
55 atlas_col_count_try <<= 1)
58 atlas_extent.z *= sh_coef_len;
61 atlas_extent.x *= atlas_col_count_try;
65 atlas_row_count =
divide_ceil_u(atlas_byte_size, row_byte_size);
66 atlas_extent.y *= atlas_row_count;
72 if (irradiance_atlas_tx_.
is_valid()) {
73 do_full_update_ =
true;
74 irradiance_pool_size_alloc_ = irradiance_pool_size;
75 atlas_col_count = atlas_col_count_try;
80 if (irradiance_pool_size_alloc_ != irradiance_pool_size_) {
82 "Warning: Could not allocate light probes volume pool of {} MB, using {} MB instead.",
83 irradiance_pool_size_,
84 irradiance_pool_size_alloc_);
87 if (do_full_update_) {
88 do_update_world_ =
true;
96 for (
auto i :
IndexRange(atlas_row_count * atlas_col_count)) {
99 world_brick_index_ = 0;
109 if (irradiance_atlas_tx_.
is_valid()) {
115 if (irradiance_atlas_tx_.
is_valid() ==
false) {
129 if (brick_pool_.
size() < brick_len) {
137 brick_pool_.
resize(brick_pool_.
size() - brick_len);
152 bool any_update =
false;
154 bricks_infos_buf_.
clear();
157 if (cache ==
nullptr) {
167 if (grid_size.x <= 0 || grid_size.y <= 0 || grid_size.z <= 0) {
182 int3 grid_size_with_padding = grid_size + 2;
183 if (grid.bricks.is_empty()) {
186 int brick_len = grid_size_in_bricks.x * grid_size_in_bricks.y * grid_size_in_bricks.z;
189 if (grid.bricks.is_empty()) {
193 grid.do_update =
true;
196 if (do_update_world_) {
198 grid.do_update =
true;
201 any_update = any_update || grid.do_update;
203 grid.brick_offset = bricks_infos_buf_.
size();
204 bricks_infos_buf_.
extend(grid.bricks);
212 grid.grid_size_padded = grid_size_with_padding;
213 grid_loaded.
append(&grid);
221 grid->do_update =
true;
226 int world_grid_index = 0;
231 float volume_a = math::determinant(float3x3(a->object_to_world));
232 float volume_b = math::determinant(float3x3(b->object_to_world));
233 if (volume_a != volume_b) {
235 return volume_a < volume_b;
240 float3 _a = a->object_to_world.location();
241 float3 _b =
b->object_to_world.location();
245 else if (_a.y != _b.y) {
248 else if (_a.z != _b.z) {
260 grid->grid_index = grids_len;
261 grids_infos_buf_[grids_len++] = *grid;
265 world_grid_index = grids_len++;
269 grid.grid_size_padded =
int3(1);
270 grid.brick_offset = bricks_infos_buf_.
size();
271 grid.normal_bias = 0.0f;
272 grid.view_bias = 0.0f;
273 grid.facing_bias = 0.0f;
274 grids_infos_buf_[world_grid_index] = grid;
276 bricks_infos_buf_.
append(world_brick_index_);
280 grids_infos_buf_[grids_len].grid_size_padded =
int3(-1);
288 if (do_update_world_) {
289 grid_upload_ps_.init();
291 grid_upload_ps_.bind_resources(inst_.uniform_data);
292 grid_upload_ps_.bind_ssbo(
"harmonic_buf", &inst_.sphere_probes.spherical_harmonics_buf());
293 grid_upload_ps_.bind_ubo(
"grids_infos_buf", &grids_infos_buf_);
294 grid_upload_ps_.bind_ssbo(
"bricks_infos_buf", &bricks_infos_buf_);
295 grid_upload_ps_.push_constant(
"grid_index", world_grid_index);
296 grid_upload_ps_.bind_image(
"irradiance_atlas_img", &irradiance_atlas_tx_);
300 grid_upload_ps_.dispatch(
int3(1));
304 inst_.manager->submit(grid_upload_ps_);
310 int grid_start_index = grid_loaded.size() + 1;
311 for (
auto it = grid_loaded.rbegin(); it != grid_loaded.rend(); ++it) {
314 VolumeProbe *grid = *it;
315 if (!grid->do_update) {
319 grid->do_update =
false;
324 draw::Texture irradiance_a_tx = {
"irradiance_a_tx"};
325 draw::Texture irradiance_b_tx = {
"irradiance_b_tx"};
326 draw::Texture irradiance_c_tx = {
"irradiance_c_tx"};
327 draw::Texture irradiance_d_tx = {
"irradiance_d_tx"};
328 draw::Texture validity_tx = {
"validity_tx"};
340 validity_tx.clear(
float4(0.0));
345 irradiance_b_tx.ensure_3d(
347 irradiance_c_tx.ensure_3d(
349 irradiance_d_tx.ensure_3d(
351 validity_tx.ensure_3d(
GPU_R8, grid_size, usage);
364 validity_tx.clear(
float4(0.0));
371 if (irradiance_a_tx.is_valid() ==
false) {
372 inst_.info_append_i18n(
"Error: Could not allocate irradiance staging texture");
382 bool visibility_available = cache->
visibility.
L0 !=
nullptr;
385 draw::Texture visibility_a_tx = {
"visibility_a_tx"};
386 draw::Texture visibility_b_tx = {
"visibility_b_tx"};
387 draw::Texture visibility_c_tx = {
"visibility_c_tx"};
388 draw::Texture visibility_d_tx = {
"visibility_d_tx"};
389 if (visibility_available) {
400 else if (!is_baking) {
408 grid_upload_ps_.init();
411 grid_upload_ps_.bind_resources(inst_.uniform_data);
412 grid_upload_ps_.push_constant(
"validity_threshold", grid->validity_threshold);
413 grid_upload_ps_.push_constant(
"dilation_threshold", grid->dilation_threshold);
414 grid_upload_ps_.push_constant(
"dilation_radius", grid->dilation_radius);
415 grid_upload_ps_.push_constant(
"grid_index", grid->grid_index);
416 grid_upload_ps_.push_constant(
"grid_start_index", grid_start_index);
417 grid_upload_ps_.push_constant(
"grid_local_to_world", grid->object_to_world);
418 grid_upload_ps_.push_constant(
"grid_intensity_factor", grid->intensity);
419 grid_upload_ps_.bind_ubo(
"grids_infos_buf", &grids_infos_buf_);
420 grid_upload_ps_.bind_ssbo(
"bricks_infos_buf", &bricks_infos_buf_);
421 grid_upload_ps_.bind_texture(
"irradiance_a_tx", &irradiance_a_tx);
422 grid_upload_ps_.bind_texture(
"irradiance_b_tx", &irradiance_b_tx);
423 grid_upload_ps_.bind_texture(
"irradiance_c_tx", &irradiance_c_tx);
424 grid_upload_ps_.bind_texture(
"irradiance_d_tx", &irradiance_d_tx);
425 grid_upload_ps_.bind_texture(
"validity_tx", &validity_tx);
426 grid_upload_ps_.bind_image(
"irradiance_atlas_img", &irradiance_atlas_tx_);
429 grid_upload_ps_.bind_texture(
"irradiance_atlas_tx", &irradiance_atlas_tx_);
432 bool use_vis = visibility_available;
433 grid_upload_ps_.bind_texture(
"visibility_a_tx", use_vis ? &visibility_a_tx : &irradiance_a_tx);
434 grid_upload_ps_.bind_texture(
"visibility_b_tx", use_vis ? &visibility_b_tx : &irradiance_b_tx);
435 grid_upload_ps_.bind_texture(
"visibility_c_tx", use_vis ? &visibility_c_tx : &irradiance_c_tx);
436 grid_upload_ps_.bind_texture(
"visibility_d_tx", use_vis ? &visibility_d_tx : &irradiance_d_tx);
439 int3 grid_size_with_padding = grid_size + 2;
443 grid_upload_ps_.dispatch(grid_size_in_bricks);
447 inst_.manager->submit(grid_upload_ps_);
449 irradiance_a_tx.free();
450 irradiance_b_tx.free();
451 irradiance_c_tx.free();
452 irradiance_d_tx.free();
455 do_full_update_ =
false;
456 do_update_world_ =
false;
459void VolumeProbeModule::viewport_draw(
View &view, GPUFrameBuffer *view_fb)
461 if (!inst_.is_baking()) {
462 debug_pass_draw(view, view_fb);
463 display_pass_draw(view, view_fb);
467void VolumeProbeModule::debug_pass_draw(
View &view, GPUFrameBuffer *view_fb)
469 switch (inst_.debug_mode) {
470 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL:
471 inst_.info_append(
"Debug Mode: Surfels Normal");
473 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_CLUSTER:
474 inst_.info_append(
"Debug Mode: Surfels Cluster");
476 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE:
477 inst_.info_append(
"Debug Mode: Surfels Irradiance");
479 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_VISIBILITY:
480 inst_.info_append(
"Debug Mode: Surfels Visibility");
482 case eDebugMode::DEBUG_IRRADIANCE_CACHE_VALIDITY:
483 inst_.info_append(
"Debug Mode: Irradiance Validity");
485 case eDebugMode::DEBUG_IRRADIANCE_CACHE_VIRTUAL_OFFSET:
486 inst_.info_append(
"Debug Mode: Virtual Offset");
493 for (
const VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
494 if (grid.cache ==
nullptr) {
500 if (cache ==
nullptr) {
504 switch (inst_.debug_mode) {
505 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL:
506 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_CLUSTER:
507 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_VISIBILITY:
508 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE: {
516 debug_ps_.framebuffer_set(&view_fb);
517 debug_ps_.shader_set(inst_.shaders.static_shader_get(DEBUG_SURFELS));
518 debug_ps_.push_constant(
"debug_surfel_radius", 0.5f * max_axis_len / grid.surfel_density);
519 debug_ps_.push_constant(
"debug_mode",
int(inst_.debug_mode));
525 MutableSpan<Surfel>(debug_surfels_buf_.data(), cache->
surfels_len).copy_from(grid_surfels);
526 debug_surfels_buf_.push_update();
528 debug_ps_.bind_ssbo(
"surfels_buf", debug_surfels_buf_);
531 inst_.manager->submit(debug_ps_, view);
535 case eDebugMode::DEBUG_IRRADIANCE_CACHE_VALIDITY:
536 case eDebugMode::DEBUG_IRRADIANCE_CACHE_VIRTUAL_OFFSET: {
541 debug_ps_.framebuffer_set(&view_fb);
542 debug_ps_.shader_set(inst_.shaders.static_shader_get(DEBUG_IRRADIANCE_GRID));
543 debug_ps_.push_constant(
"debug_mode",
int(inst_.debug_mode));
544 debug_ps_.push_constant(
"grid_mat", grid.object_to_world);
547 Texture debug_data_tx = {
"debug_data_tx"};
549 if (inst_.debug_mode == eDebugMode::DEBUG_IRRADIANCE_CACHE_VALIDITY) {
553 debug_data_tx.ensure_3d(
GPU_R16F, grid_size, usage, data);
556 debug_data_tx.ensure_3d(
GPU_R8, grid_size, usage);
569 debug_ps_.push_constant(
"debug_value", grid.validity_threshold);
570 debug_ps_.bind_texture(
"debug_data_tx", debug_data_tx);
571 debug_ps_.draw_procedural(
GPU_PRIM_POINTS, 1, grid_size.
x * grid_size.
y * grid_size.
z);
576 debug_data_tx.ensure_3d(
GPU_RGBA16F, grid_size, usage, data);
581 debug_ps_.bind_texture(
"debug_data_tx", debug_data_tx);
582 debug_ps_.draw_procedural(
586 inst_.manager->submit(debug_ps_, view);
596void VolumeProbeModule::display_pass_draw(View &view, GPUFrameBuffer *view_fb)
598 if (!display_grids_enabled_) {
602 for (
const VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
603 if (!grid.viewport_display || grid.viewport_display_size == 0.0f || !grid.cache ||
604 !grid.cache->grid_static_cache)
612 draw::Texture irradiance_a_tx = {
"irradiance_a_tx"};
613 draw::Texture irradiance_b_tx = {
"irradiance_b_tx"};
614 draw::Texture irradiance_c_tx = {
"irradiance_c_tx"};
615 draw::Texture irradiance_d_tx = {
"irradiance_d_tx"};
616 draw::Texture validity_tx = {
"validity_tx"};
628 validity_tx.clear(
float4(0.0));
633 irradiance_b_tx.ensure_3d(
635 irradiance_c_tx.ensure_3d(
637 irradiance_d_tx.ensure_3d(
639 validity_tx.ensure_3d(
GPU_R8, grid_size, usage);
652 validity_tx.clear(
float4(0.0));
659 display_grids_ps_.init();
662 display_grids_ps_.framebuffer_set(&view_fb);
663 display_grids_ps_.shader_set(inst_.shaders.static_shader_get(DISPLAY_PROBE_VOLUME));
665 display_grids_ps_.push_constant(
"sphere_radius", grid.viewport_display_size);
666 display_grids_ps_.push_constant(
"grid_resolution", grid_size);
667 display_grids_ps_.push_constant(
"grid_to_world", grid.object_to_world);
668 display_grids_ps_.push_constant(
"world_to_grid", grid.world_to_object);
670 display_grids_ps_.push_constant(
"display_validity",
false);
672 display_grids_ps_.bind_texture(
"irradiance_a_tx", &irradiance_a_tx);
673 display_grids_ps_.bind_texture(
"irradiance_b_tx", &irradiance_b_tx);
674 display_grids_ps_.bind_texture(
"irradiance_c_tx", &irradiance_c_tx);
675 display_grids_ps_.bind_texture(
"irradiance_d_tx", &irradiance_d_tx);
676 display_grids_ps_.bind_texture(
"validity_tx", &validity_tx);
679 int triangle_count = sample_count * 2;
680 display_grids_ps_.draw_procedural(
GPU_PRIM_TRIS, 1, triangle_count * 3);
682 inst_.manager->submit(display_grids_ps_, view);
684 irradiance_a_tx.free();
685 irradiance_b_tx.free();
686 irradiance_c_tx.free();
687 irradiance_d_tx.free();
697void IrradianceBake::init(
const Object &probe_object)
701 const ::LightProbe *lightprobe =
static_cast<::
LightProbe *
>(probe_object.
data);
702 surfel_density_ = lightprobe->grid_surfel_density / max_axis_len;
703 min_distance_to_surface_ = lightprobe->grid_surface_bias;
704 max_virtual_offset_ = lightprobe->grid_escape_bias;
705 clip_distance_ = lightprobe->clipend;
714void IrradianceBake::sync()
720 pass.shader_set(inst_.shaders.static_shader_get(
SURFEL_LIGHT));
724 pass.bind_resources(inst_.uniform_data);
725 pass.bind_resources(inst_.lights);
726 pass.bind_resources(inst_.shadows);
731 pass.dispatch(&dispatch_per_surfel_);
739 pass.bind_image(
"cluster_list_img", &cluster_list_tx_);
741 pass.dispatch(&dispatch_per_surfel_);
752 sub.
bind_ssbo(
"list_start_buf", &list_start_buf_);
753 sub.
bind_ssbo(
"list_info_buf", &list_info_buf_);
755 sub.
dispatch(&dispatch_per_surfel_);
762 sub.
bind_ssbo(
"list_start_buf", &list_start_buf_);
763 sub.
bind_ssbo(
"list_info_buf", &list_info_buf_);
769 PassSimple &pass = surfel_light_propagate_ps_;
780 sub.
dispatch(&dispatch_per_surfel_);
789 pass.bind_resources(inst_.sphere_probes);
790 pass.bind_ssbo(
"list_start_buf", &list_start_buf_);
791 pass.bind_ssbo(
"list_info_buf", &list_info_buf_);
792 pass.push_constant(
"radiance_src", &radiance_src_);
793 pass.bind_image(
"irradiance_L0_img", &irradiance_L0_tx_);
794 pass.bind_image(
"irradiance_L1_a_img", &irradiance_L1_a_tx_);
795 pass.bind_image(
"irradiance_L1_b_img", &irradiance_L1_b_tx_);
796 pass.bind_image(
"irradiance_L1_c_img", &irradiance_L1_c_tx_);
797 pass.bind_image(
"validity_img", &validity_tx_);
798 pass.bind_image(
"virtual_offset_img", &virtual_offset_tx_);
800 pass.dispatch(&dispatch_per_grid_sample_);
808 pass.bind_ssbo(
"list_start_buf", &list_start_buf_);
809 pass.bind_ssbo(
"list_info_buf", &list_info_buf_);
810 pass.bind_image(
"cluster_list_img", &cluster_list_tx_);
811 pass.bind_image(
"virtual_offset_img", &virtual_offset_tx_);
813 pass.dispatch(&dispatch_per_grid_sample_);
817void IrradianceBake::surfel_raster_views_sync(
const float3 &scene_min,
827 float4x4 viewinv = from_loc_rot_scale<float4x4>(location, rotation,
float3(1.0f));
833 for (
int x : {0, 1}) {
834 for (
int y : {0, 1}) {
835 for (
int z : {0, 1}) {
836 float3 ws_corner = scene_min + ((scene_max - scene_min) *
float3(x, y,
z));
838 extent_min =
min(extent_min, ls_corner);
839 extent_max =
max(extent_max, ls_corner);
844 float3 target_extent = scale + clip_distance_;
845 extent_min =
max(extent_min, -target_extent);
846 extent_max =
min(extent_max, target_extent);
848 grid_pixel_extent_ =
max(
int3(1),
int3(surfel_density_ * (extent_max - extent_min)));
849 grid_pixel_extent_ =
min(grid_pixel_extent_,
int3(16384));
853 distance(extent_min, extent_max) / 2.0f);
858 float4x4 capture_viewinv = viewinv * from_rotation<float4x4>(basis);
863 float4x4 capture_winmat = projection::orthographic(capture_extent_min.x,
864 capture_extent_max.x,
865 capture_extent_min.y,
866 capture_extent_max.y,
867 -capture_extent_min.z,
868 -capture_extent_max.z);
870 view.visibility_test(
false);
871 view.sync(
invert(capture_viewinv), capture_winmat);
874 sync_view(view_x_, basis_x_);
875 sync_view(view_y_, basis_y_);
876 sync_view(view_z_, basis_z_);
879void IrradianceBake::surfels_create(
const Object &probe_object)
888 const ::LightProbe *lightprobe =
static_cast<::
LightProbe *
>(probe_object.
data);
890 int3 grid_resolution =
int3(&lightprobe->grid_resolution_x);
891 float4x4 grid_local_to_world =
invert(probe_object.world_to_object());
895 capture_info_buf_.capture_world_direct = capture_world_;
896 capture_info_buf_.capture_world_indirect = capture_world_ && capture_indirect_;
897 capture_info_buf_.capture_visibility_direct = !capture_world_;
898 capture_info_buf_.capture_visibility_indirect = !(capture_world_ && capture_indirect_);
899 capture_info_buf_.capture_indirect = capture_indirect_;
900 capture_info_buf_.capture_emission = capture_emission_;
904 capture_info_buf_.world_atlas_coord = world_data.
atlas_coord;
907 capture_info_buf_.irradiance_grid_size = grid_resolution;
908 capture_info_buf_.irradiance_grid_local_to_world = grid_local_to_world;
909 capture_info_buf_.irradiance_grid_world_to_local = probe_object.world_to_object();
910 capture_info_buf_.irradiance_grid_world_to_local_rotation =
float4x4(
913 capture_info_buf_.min_distance_to_surface = min_distance_to_surface_;
914 capture_info_buf_.max_virtual_offset = max_virtual_offset_;
915 capture_info_buf_.surfel_radius = 0.5f / surfel_density_;
918 capture_info_buf_.min_distance_to_surface *= min_distance_between_grid_samples;
919 capture_info_buf_.max_virtual_offset *= min_distance_between_grid_samples;
920 capture_info_buf_.clamp_direct = (lightprobe->grid_clamp_direct > 0.0) ?
921 lightprobe->grid_clamp_direct :
923 capture_info_buf_.clamp_indirect = (lightprobe->grid_clamp_indirect > 0.0) ?
924 lightprobe->grid_clamp_indirect :
932 irradiance_L0_tx_.ensure_3d(
GPU_RGBA32F, grid_resolution, texture_usage);
933 irradiance_L1_a_tx_.ensure_3d(
GPU_RGBA32F, grid_resolution, texture_usage);
934 irradiance_L1_b_tx_.ensure_3d(
GPU_RGBA32F, grid_resolution, texture_usage);
935 irradiance_L1_c_tx_.ensure_3d(
GPU_RGBA32F, grid_resolution, texture_usage);
936 validity_tx_.ensure_3d(
GPU_R32F, grid_resolution, texture_usage);
937 virtual_offset_tx_.ensure_3d(
GPU_RGBA16F, grid_resolution, texture_usage);
939 if (!irradiance_L0_tx_.is_valid() || !irradiance_L1_a_tx_.is_valid() ||
940 !irradiance_L1_b_tx_.is_valid() || !irradiance_L1_c_tx_.is_valid() ||
941 !validity_tx_.is_valid() || !virtual_offset_tx_.is_valid())
943 inst_.info_append_i18n(
"Error: Not enough memory to bake {}.", probe_object.
id.
name);
948 irradiance_L0_tx_.clear(
float4(0.0f));
949 irradiance_L1_a_tx_.clear(
float4(0.0f));
950 irradiance_L1_b_tx_.clear(
float4(0.0f));
951 irradiance_L1_c_tx_.clear(
float4(0.0f));
952 validity_tx_.clear(
float4(0.0f));
953 virtual_offset_tx_.clear(
float4(0.0f));
962 pass.bind_ssbo(
"capture_info_buf", &capture_info_buf_);
963 pass.bind_ssbo(
"bounds_buf", &manager.
bounds_buf.current());
970 capture_info_buf_.do_surfel_count =
false;
971 capture_info_buf_.do_surfel_output =
false;
973 const int neg_flt_max =
int(0xFF7FFFFFu ^ 0x7FFFFFFFu);
974 const int pos_flt_max = 0x7F7FFFFF;
975 capture_info_buf_.scene_bound_x_min = pos_flt_max;
976 capture_info_buf_.scene_bound_y_min = pos_flt_max;
977 capture_info_buf_.scene_bound_z_min = pos_flt_max;
978 capture_info_buf_.scene_bound_x_max = neg_flt_max;
979 capture_info_buf_.scene_bound_y_max = neg_flt_max;
980 capture_info_buf_.scene_bound_z_max = neg_flt_max;
982 capture_info_buf_.push_update();
984 inst_.manager->submit(irradiance_bounds_ps_);
987 capture_info_buf_.read();
989 if (capture_info_buf_.scene_bound_x_min == pos_flt_max) {
995 auto ordered_int_bits_to_float = [](
int32_t int_value) ->
float {
996 int32_t float_bits = (int_value < 0) ? (int_value ^ 0x7FFFFFFF) : int_value;
997 return *
reinterpret_cast<float *
>(&float_bits);
1000 float3 scene_min =
float3(ordered_int_bits_to_float(capture_info_buf_.scene_bound_x_min),
1001 ordered_int_bits_to_float(capture_info_buf_.scene_bound_y_min),
1002 ordered_int_bits_to_float(capture_info_buf_.scene_bound_z_min));
1003 float3 scene_max =
float3(ordered_int_bits_to_float(capture_info_buf_.scene_bound_x_max),
1004 ordered_int_bits_to_float(capture_info_buf_.scene_bound_y_max),
1005 ordered_int_bits_to_float(capture_info_buf_.scene_bound_z_max));
1007 float epsilon = 1.0f / surfel_density_;
1008 scene_min -= epsilon;
1009 scene_max += epsilon;
1010 surfel_raster_views_sync(scene_min, scene_max, probe_object.object_to_world());
1015 inst_.camera.sync();
1018 inst_.shadows.end_sync();
1019 inst_.lights.end_sync();
1024 capture_info_buf_.do_surfel_count =
true;
1025 capture_info_buf_.do_surfel_output =
false;
1026 capture_info_buf_.surfel_len = 0u;
1027 capture_info_buf_.push_update();
1030 inst_.pipelines.capture.render(view_x_);
1032 inst_.pipelines.capture.render(view_y_);
1034 inst_.pipelines.capture.render(view_z_);
1040 capture_info_buf_.read();
1041 if (capture_info_buf_.surfel_len == 0) {
1046 if (capture_info_buf_.surfel_len > surfels_buf_.size()) {
1047 printf(
"IrradianceBake: Allocating %u surfels.\n", capture_info_buf_.surfel_len);
1051 int total_mem_kb, free_mem_kb;
1055 size_t max_alloc = (size_t(total_mem_kb) - 128 * 1024) * 1024;
1057 size_t max_free = size_t((
size_t(free_mem_kb) * 1024) * 0.95f);
1059 max_size =
min(max_size,
min(max_alloc, max_free));
1062 size_t required_mem =
sizeof(
Surfel) * (capture_info_buf_.surfel_len - surfels_buf_.size());
1063 if (required_mem > max_size) {
1065 const uint req_mb = required_mem / (1024 * 1024);
1066 const uint max_mb = max_size / (1024 * 1024);
1068 if (is_ssbo_bound) {
1069 inst_.info_append_i18n(
1070 "Cannot allocate enough video memory to bake \"{}\" ({} / {} MBytes).\n"
1071 "Try reducing surfel resolution or capture distance to lower the size of the "
1078 inst_.info_append_i18n(
1079 "Not enough available video memory to bake \"{}\" ({} / {} MBytes).\n"
1080 "Try reducing surfel resolution or capture distance to lower the size of the "
1089 fprintf(stderr,
"%s", inst_.info_get());
1097 surfels_buf_.resize(capture_info_buf_.surfel_len);
1098 surfels_buf_.clear_to_zero();
1105 capture_info_buf_.do_surfel_count =
true;
1106 capture_info_buf_.do_surfel_output =
true;
1107 capture_info_buf_.surfel_len = 0u;
1108 capture_info_buf_.push_update();
1111 inst_.pipelines.capture.render(view_x_);
1113 inst_.pipelines.capture.render(view_y_);
1115 inst_.pipelines.capture.render(view_z_);
1120 capture_info_buf_.read();
1125void IrradianceBake::surfels_lights_eval()
1129 inst_.render_buffers.acquire(
int2(1));
1130 inst_.hiz_buffer.set_source(&inst_.render_buffers.depth_tx);
1131 inst_.lights.set_view(view_z_, grid_pixel_extent_.xy());
1132 inst_.shadows.set_view(view_z_, grid_pixel_extent_.xy());
1133 inst_.render_buffers.release();
1135 inst_.manager->submit(surfel_light_eval_ps_, view_z_);
1138void IrradianceBake::clusters_build()
1140 if (max_virtual_offset_ == 0.0f) {
1146 cluster_list_tx_.ensure_3d(
GPU_R32I, capture_info_buf_.irradiance_grid_size, texture_usage);
1147 cluster_list_tx_.clear(
int4(-1));
1149 inst_.manager->submit(surfel_cluster_build_ps_, view_z_);
1152void IrradianceBake::irradiance_offset()
1154 if (max_virtual_offset_ == 0.0f) {
1159 inst_.manager->submit(irradiance_offset_ps_, view_z_);
1162 cluster_list_tx_.free();
1165void IrradianceBake::raylists_build()
1169 float2 rand_uv = inst_.sampling.rng_2d_get(eSamplingDimension::SAMPLING_LENS_U);
1170 const float3 ray_direction = inst_.sampling.sample_sphere(rand_uv);
1171 const float3 up = ray_direction;
1173 const float4x4 viewinv = from_orthonormal_axes<float4x4>(
float3(0.0f), forward, up);
1179 min -= scene_bound_sphere_.w;
1180 max += scene_bound_sphere_.w;
1194 const float max_distance_between_neighbor_surfels_inv =
M_SQRT1_2 - 1
e-4;
1196 const float ray_grid_density = surfel_density_ * max_distance_between_neighbor_surfels_inv;
1198 const float pixel_size = 1.0f / ray_grid_density;
1204 list_info_buf_.ray_grid_size +=
int2(4);
1205 min -= pixel_size * 2.0f;
1206 max += pixel_size * 2.0f;
1209 const float2 aa_rand = inst_.sampling.rng_2d_get(eSamplingDimension::SAMPLING_FILTER_U);
1211 const float2 aa_offset = (aa_rand - 0.5f) * 0.499f;
1212 min += pixel_size * aa_offset;
1214 list_info_buf_.list_max = list_info_buf_.ray_grid_size.x * list_info_buf_.ray_grid_size.y;
1215 list_info_buf_.push_update();
1218 const float4x4 winmat = projection::orthographic<float>(
min.x, max.x,
min.y, max.y, 0, 1);
1220 ray_view_.sync(viewmat, winmat);
1227 inst_.manager->submit(surfel_ray_build_ps_, ray_view_);
1230void IrradianceBake::propagate_light()
1233 capture_info_buf_.sample_index = inst_.sampling.sample_index() - 1;
1234 capture_info_buf_.sample_count = inst_.sampling.sample_count();
1235 capture_info_buf_.push_update();
1237 inst_.manager->submit(surfel_light_propagate_ps_, ray_view_);
1239 std::swap(radiance_src_, radiance_dst_);
1242void IrradianceBake::irradiance_capture()
1244 inst_.manager->submit(irradiance_capture_ps_, ray_view_);
1249 if (!
ELEM(inst_.debug_mode,
1250 eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_CLUSTER,
1251 eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL,
1252 eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE,
1253 eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_VISIBILITY))
1259 capture_info_buf_.read();
1260 surfels_buf_.read();
1262 cache_frame->
surfels_len = capture_info_buf_.surfel_len;
1267 surfels_dst.copy_from(surfels_src);
1272 if (!
ELEM(inst_.debug_mode, eDebugMode::DEBUG_IRRADIANCE_CACHE_VIRTUAL_OFFSET)) {
1286 read_surfels(cache_frame);
1287 read_virtual_offset(cache_frame);
1289 cache_frame->
size[0] = irradiance_L0_tx_.width();
1290 cache_frame->
size[1] = irradiance_L0_tx_.height();
1291 cache_frame->
size[2] = irradiance_L0_tx_.depth();
1308 read_surfels(cache_frame);
1309 read_virtual_offset(cache_frame);
1311 cache_frame->
size[0] = irradiance_L0_tx_.width();
1312 cache_frame->
size[1] = irradiance_L0_tx_.height();
1313 cache_frame->
size[2] = irradiance_L0_tx_.depth();
1323 int64_t sample_count =
int64_t(irradiance_L0_tx_.width()) * irradiance_L0_tx_.height() *
1324 irradiance_L0_tx_.depth();
1325 size_t coefficient_texture_size =
sizeof(*cache_frame->
irradiance.
L0) * sample_count;
1333 size_t visibility_texture_size =
sizeof(*cache_frame->
irradiance.
L0) * sample_count;
General operations for probes.
struct LightProbeGridCacheFrame * BKE_lightprobe_grid_cache_frame_create(void)
int64_t BKE_lightprobe_grid_cache_frame_sample_count(const struct LightProbeGridCacheFrame *cache)
MINLINE uint ceil_to_multiple_u(uint a, uint b)
MINLINE uint divide_ceil_u(uint a, uint b)
MINLINE void copy_v3_v3(float r[3], const float a[3])
@ LIGHTPROBE_GRID_CAPTURE_EMISSION
@ LIGHTPROBE_GRID_CAPTURE_WORLD
@ LIGHTPROBE_GRID_CAPTURE_INDIRECT
void GPU_mem_stats_get(int *r_totalmem, int *r_freemem)
bool GPU_mem_stats_supported()
size_t GPU_max_storage_buffer_size()
void GPU_memory_barrier(eGPUBarrier barrier)
@ GPU_BARRIER_SHADER_STORAGE
@ GPU_BARRIER_TEXTURE_FETCH
@ GPU_BARRIER_BUFFER_UPDATE
@ GPU_BARRIER_SHADER_IMAGE_ACCESS
@ GPU_BARRIER_TEXTURE_UPDATE
void GPU_storagebuf_clear(GPUStorageBuf *ssbo, uint32_t clear_value)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_HOST_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_TEXTURE_USAGE_ATOMIC
void GPU_texture_update_sub(GPUTexture *texture, eGPUDataFormat data_format, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
void GPU_texture_swizzle_set(GPUTexture *texture, const char swizzle[4])
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
void append(const T &value)
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
void extend(Span< T > array)
Span< T > as_span() const
SwapChain< ObjectBoundsBuf, 2 > bounds_buf
uint resource_handle_count() const
void append(const T &value)
void extend(const Span< T > values)
void clear(float4 values)
bool ensure_3d(eGPUTextureFormat format, int3 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
void bind_resources(U &resources)
PassBase< DrawCommandBufType > & sub(const char *name)
void dispatch(int group_len)
void barrier(eGPUBarrier type)
void push_constant(const char *name, const float &data)
void bind_ssbo(const char *name, GPUStorageBuf *buffer)
void shader_set(GPUShader *shader)
void info_append_i18n(const char *msg, Args &&...args)
LightProbeModule light_probes
void set_view(View &view)
Vector< IrradianceBrickPacked > bricks_alloc(int brick_len)
void bricks_free(Vector< IrradianceBrickPacked > &bricks)
local_group_size(16, 16) .push_constant(Type b
additional_info("compositor_sum_float_shared") .push_constant(Type additional_info("compositor_sum_float_shared") .push_constant(Type GPU_RGBA32F
bool DRW_state_draw_support()
void DRW_stats_group_start(const char *name)
void DRW_stats_group_end()
@ DRW_STATE_DEPTH_LESS_EQUAL
#define SURFEL_GROUP_SIZE
#define IRRADIANCE_BOUNDS_GROUP_SIZE
#define RBUFS_UTILITY_TEX_SLOT
#define SURFEL_LIST_GROUP_SIZE
#define IRRADIANCE_GRID_MAX
#define IRRADIANCE_GRID_BRICK_SIZE
#define IRRADIANCE_GRID_GROUP_SIZE
#define VOLUME_PROBE_FORMAT
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
BLI_INLINE void grid_to_world(HairGrid *grid, float vecw[3], const float vec[3])
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
void *(* MEM_mallocN)(size_t len, const char *str)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
#define unit_float_to_uchar_clamp(val)
ccl_device_inline float cross(const float2 a, const float2 b)
@ LIGHTPROBE_IRRADIANCE_RAY
@ LIGHTPROBE_IRRADIANCE_LOAD
@ LIGHTPROBE_IRRADIANCE_OFFSET
@ LIGHTPROBE_IRRADIANCE_WORLD
@ LIGHTPROBE_IRRADIANCE_BOUNDS
static IrradianceBrickPacked irradiance_brick_pack(IrradianceBrick brick)
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
T reduce_max(const VecBase< T, Size > &a)
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T reduce_min(const VecBase< T, Size > &a)
CartesianBasis invert(const CartesianBasis &basis)
T midpoint(const T &a, const T &b)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
T reduce_mul(const VecBase< T, Size > &a)
VecBase< T, 3 > to_scale(const MatBase< T, NumCol, NumRow > &mat)
T max(const T &a, const T &b)
MatT from_location(const typename MatT::loc_type &location)
void to_loc_rot_scale(const MatBase< T, 3, 3 > &mat, VecBase< T, 2 > &r_location, AngleRadianBase< T > &r_rotation, VecBase< T, 2 > &r_scale)
VecBase< uint32_t, 2 > uint2
VecBase< int32_t, 4 > int4
bool assign_if_different(T &old_value, T new_value)
MatBase< float, 4, 4 > float4x4
MatBase< float, 3, 4 > float3x4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< int32_t, 3 > int3
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
float distance(float a, float b)
float(* virtual_offset)[4]
LightProbeVisibilityData visibility
LightProbeBakingData baking
LightProbeConnectivityData connectivity
LightProbeIrradianceData irradiance
int gi_irradiance_pool_size
static MatBase identity()
VecBase< T, 2 > xy() const
SphereProbeUvArea atlas_coord
float3x4 world_to_grid_transposed