28 display_grids_enabled_ = inst_.draw_overlays;
31 bool use_l2_band =
false;
32 int sh_coef_len = use_l2_band ? 9 : 4;
33 BLI_assert(gpu::TextureFormat::VOLUME_PROBE_FORMAT == gpu::TextureFormat::SFLOAT_16_16_16_16);
34 int texel_byte_size = 8;
35 uint atlas_col_count = 0;
36 uint atlas_row_count = 0;
39 uint(inst_.scene->eevee.gi_irradiance_pool_size)) ||
40 !irradiance_atlas_tx_.is_valid())
42 irradiance_atlas_tx_.free();
44 for (
uint irradiance_pool_size = irradiance_pool_size_;
45 irradiance_pool_size >= 16 && !irradiance_atlas_tx_.is_valid();
46 irradiance_pool_size >>= 1)
48 int atlas_byte_size = 1024 * 1024 * irradiance_pool_size;
50 constexpr uint atlas_col_count_min = 16;
51 constexpr uint atlas_col_count_max = 16384;
52 for (
uint atlas_col_count_try = atlas_col_count_min;
53 atlas_col_count_try <= atlas_col_count_max && !irradiance_atlas_tx_.is_valid();
54 atlas_col_count_try <<= 1)
57 atlas_extent.z *= sh_coef_len;
60 atlas_extent.x *= atlas_col_count_try;
64 atlas_row_count =
divide_ceil_u(atlas_byte_size, row_byte_size);
65 atlas_extent.y *= atlas_row_count;
70 irradiance_atlas_tx_.ensure_3d(
71 gpu::TextureFormat::VOLUME_PROBE_FORMAT, atlas_extent, usage);
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_) {
81 inst_.info_append_i18n(
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_full_update_ =
false;
89 do_update_world_ =
true;
92 for (
VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
97 for (
auto i :
IndexRange(atlas_row_count * atlas_col_count)) {
100 world_brick_index_ = 0;
110 if (irradiance_atlas_tx_.is_valid()) {
112 irradiance_atlas_tx_.clear(
float4(0.0f));
116 if (irradiance_atlas_tx_.is_valid() ==
false) {
117 inst_.info_append_i18n(
"Irradiance Atlas texture could not be created");
123 if (inst_.is_baking()) {
130 if (brick_pool_.size() < brick_len) {
136 allocated.
as_mutable_span().copy_from(brick_pool_.as_span().take_back(brick_len));
138 brick_pool_.resize(brick_pool_.size() - brick_len);
153 bool any_update =
false;
155 bricks_infos_buf_.
clear();
156 for (
VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
158 if (cache ==
nullptr) {
168 if (grid_size.x <= 0 || grid_size.y <= 0 || grid_size.z <= 0) {
169 inst_.info_append_i18n(
"Error: Malformed irradiance grid data");
177 inst_.info_append_i18n(
"Error: Too many irradiance grids in the scene");
183 int3 grid_size_with_padding = grid_size + 2;
184 if (grid.bricks.is_empty()) {
187 int brick_len = grid_size_in_bricks.x * grid_size_in_bricks.y * grid_size_in_bricks.z;
190 if (grid.bricks.is_empty()) {
191 inst_.info_append_i18n(
"Error: Irradiance grid allocation failed");
194 grid.do_update =
true;
197 if (do_update_world_) {
199 grid.do_update =
true;
202 any_update = any_update || grid.do_update;
204 grid.brick_offset = bricks_infos_buf_.size();
205 bricks_infos_buf_.extend(grid.bricks);
213 grid.grid_size_padded = grid_size_with_padding;
214 grid_loaded.
append(&grid);
222 grid->do_update =
true;
227 int world_grid_index = 0;
232 float volume_a = math::determinant(float3x3(a->object_to_world));
233 float volume_b = math::determinant(float3x3(b->object_to_world));
234 if (volume_a != volume_b) {
236 return volume_a < volume_b;
242 float3 _b =
b->object_to_world.location();
259 grid->grid_index = grids_len;
260 grids_infos_buf_[grids_len++] = *grid;
264 world_grid_index = grids_len++;
273 grids_infos_buf_[world_grid_index] = grid;
275 bricks_infos_buf_.append(world_brick_index_);
279 grids_infos_buf_[grids_len].grid_size_padded =
int3(-1);
282 bricks_infos_buf_.push_update();
283 grids_infos_buf_.push_update();
287 if (do_update_world_) {
288 grid_upload_ps_.init();
290 grid_upload_ps_.bind_resources(inst_.uniform_data);
291 grid_upload_ps_.bind_ssbo(
"harmonic_buf", &inst_.sphere_probes.spherical_harmonics_buf());
292 grid_upload_ps_.bind_ubo(
"grids_infos_buf", &grids_infos_buf_);
293 grid_upload_ps_.bind_ssbo(
"bricks_infos_buf", &bricks_infos_buf_);
294 grid_upload_ps_.push_constant(
"grid_index", world_grid_index);
295 grid_upload_ps_.bind_image(
"irradiance_atlas_img", &irradiance_atlas_tx_);
299 grid_upload_ps_.dispatch(
int3(1));
303 inst_.manager->submit(grid_upload_ps_);
309 int grid_start_index = grid_loaded.size() + 1;
310 for (
auto it = grid_loaded.rbegin(); it != grid_loaded.rend(); ++it) {
313 VolumeProbe *grid = *it;
314 if (!grid->do_update) {
318 grid->do_update =
false;
323 draw::Texture irradiance_a_tx = {
"irradiance_a_tx"};
324 draw::Texture irradiance_b_tx = {
"irradiance_b_tx"};
325 draw::Texture irradiance_c_tx = {
"irradiance_c_tx"};
326 draw::Texture irradiance_d_tx = {
"irradiance_d_tx"};
327 draw::Texture validity_tx = {
"validity_tx"};
332 irradiance_a_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16_16,
336 irradiance_b_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16_16,
340 irradiance_c_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16_16,
344 irradiance_d_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16_16,
348 validity_tx.ensure_3d(
349 gpu::TextureFormat::SFLOAT_16, grid_size, usage, cache->
baking.
validity);
352 validity_tx.clear(
float4(0.0));
356 irradiance_a_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
360 irradiance_b_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
364 irradiance_c_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
368 irradiance_d_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
372 validity_tx.ensure_3d(gpu::TextureFormat::UNORM_8, grid_size, usage);
385 validity_tx.clear(
float4(0.0));
392 if (irradiance_a_tx.is_valid() ==
false) {
393 inst_.info_append_i18n(
"Error: Could not allocate irradiance staging texture");
396 irradiance_a_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
int3(1), usage, zero);
397 irradiance_b_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
int3(1), usage, zero);
398 irradiance_c_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
int3(1), usage, zero);
399 irradiance_d_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
int3(1), usage, zero);
400 validity_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16,
int3(1), usage, zero);
403 bool visibility_available = cache->
visibility.
L0 !=
nullptr;
406 draw::Texture visibility_a_tx = {
"visibility_a_tx"};
407 draw::Texture visibility_b_tx = {
"visibility_b_tx"};
408 draw::Texture visibility_c_tx = {
"visibility_c_tx"};
409 draw::Texture visibility_d_tx = {
"visibility_d_tx"};
410 if (visibility_available) {
411 visibility_a_tx.ensure_3d(
412 gpu::TextureFormat::SFLOAT_16, grid_size, usage, (
const float *)cache->
visibility.
L0);
413 visibility_b_tx.ensure_3d(
414 gpu::TextureFormat::SFLOAT_16, grid_size, usage, (
const float *)cache->
visibility.
L1_a);
415 visibility_c_tx.ensure_3d(
416 gpu::TextureFormat::SFLOAT_16, grid_size, usage, (
const float *)cache->
visibility.
L1_b);
417 visibility_d_tx.ensure_3d(
418 gpu::TextureFormat::SFLOAT_16, grid_size, usage, (
const float *)cache->
visibility.
L1_c);
425 else if (!is_baking) {
433 grid_upload_ps_.init();
436 grid_upload_ps_.bind_resources(inst_.uniform_data);
437 grid_upload_ps_.push_constant(
"validity_threshold", grid->validity_threshold);
438 grid_upload_ps_.push_constant(
"dilation_threshold", grid->dilation_threshold);
439 grid_upload_ps_.push_constant(
"dilation_radius", grid->dilation_radius);
440 grid_upload_ps_.push_constant(
"grid_index", grid->grid_index);
441 grid_upload_ps_.push_constant(
"grid_start_index", grid_start_index);
442 grid_upload_ps_.push_constant(
"grid_local_to_world", grid->object_to_world);
443 grid_upload_ps_.push_constant(
"grid_intensity_factor", grid->intensity);
444 grid_upload_ps_.bind_ubo(
"grids_infos_buf", &grids_infos_buf_);
445 grid_upload_ps_.bind_ssbo(
"bricks_infos_buf", &bricks_infos_buf_);
446 grid_upload_ps_.bind_texture(
"irradiance_a_tx", &irradiance_a_tx);
447 grid_upload_ps_.bind_texture(
"irradiance_b_tx", &irradiance_b_tx);
448 grid_upload_ps_.bind_texture(
"irradiance_c_tx", &irradiance_c_tx);
449 grid_upload_ps_.bind_texture(
"irradiance_d_tx", &irradiance_d_tx);
450 grid_upload_ps_.bind_texture(
"validity_tx", &validity_tx);
451 grid_upload_ps_.bind_image(
"irradiance_atlas_img", &irradiance_atlas_tx_);
454 grid_upload_ps_.bind_texture(
"irradiance_atlas_tx", &irradiance_atlas_tx_);
457 bool use_vis = visibility_available;
458 grid_upload_ps_.bind_texture(
"visibility_a_tx", use_vis ? &visibility_a_tx : &irradiance_a_tx);
459 grid_upload_ps_.bind_texture(
"visibility_b_tx", use_vis ? &visibility_b_tx : &irradiance_b_tx);
460 grid_upload_ps_.bind_texture(
"visibility_c_tx", use_vis ? &visibility_c_tx : &irradiance_c_tx);
461 grid_upload_ps_.bind_texture(
"visibility_d_tx", use_vis ? &visibility_d_tx : &irradiance_d_tx);
464 int3 grid_size_with_padding = grid_size + 2;
468 grid_upload_ps_.dispatch(grid_size_in_bricks);
472 inst_.manager->submit(grid_upload_ps_);
474 irradiance_a_tx.free();
475 irradiance_b_tx.free();
476 irradiance_c_tx.free();
477 irradiance_d_tx.free();
480 do_update_world_ =
false;
485 if (!inst_.is_baking()) {
486 debug_pass_draw(
view, view_fb);
487 display_pass_draw(
view, view_fb);
493 switch (inst_.debug_mode) {
495 inst_.info_append(
"Debug Mode: Surfels Normal");
498 inst_.info_append(
"Debug Mode: Surfels Cluster");
501 inst_.info_append(
"Debug Mode: Surfels Irradiance");
504 inst_.info_append(
"Debug Mode: Surfels Visibility");
507 inst_.info_append(
"Debug Mode: Irradiance Validity");
510 inst_.info_append(
"Debug Mode: Virtual Offset");
517 for (
const VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
518 if (grid.cache ==
nullptr) {
524 if (cache ==
nullptr) {
528 switch (inst_.debug_mode) {
529 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL:
530 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_CLUSTER:
531 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_VISIBILITY:
532 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE: {
540 debug_ps_.framebuffer_set(&view_fb);
541 debug_ps_.shader_set(inst_.shaders.static_shader_get(DEBUG_SURFELS));
542 debug_ps_.push_constant(
"debug_surfel_radius", 0.5f * max_axis_len / grid.surfel_density);
543 debug_ps_.push_constant(
"debug_mode",
int(inst_.debug_mode));
550 debug_surfels_buf_.push_update();
552 debug_ps_.bind_ssbo(
"surfels_buf", debug_surfels_buf_);
555 inst_.manager->submit(debug_ps_,
view);
559 case eDebugMode::DEBUG_IRRADIANCE_CACHE_VALIDITY:
560 case eDebugMode::DEBUG_IRRADIANCE_CACHE_VIRTUAL_OFFSET: {
565 debug_ps_.framebuffer_set(&view_fb);
566 debug_ps_.shader_set(inst_.shaders.static_shader_get(DEBUG_IRRADIANCE_GRID));
567 debug_ps_.push_constant(
"debug_mode",
int(inst_.debug_mode));
568 debug_ps_.push_constant(
"grid_mat", grid.object_to_world);
571 Texture debug_data_tx = {
"debug_data_tx"};
573 if (inst_.debug_mode == eDebugMode::DEBUG_IRRADIANCE_CACHE_VALIDITY) {
577 debug_data_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16, grid_size, usage,
data);
580 debug_data_tx.ensure_3d(gpu::TextureFormat::UNORM_8, grid_size, usage);
593 debug_ps_.push_constant(
"debug_value", grid.validity_threshold);
594 debug_ps_.bind_texture(
"debug_data_tx", debug_data_tx);
595 debug_ps_.draw_procedural(
GPU_PRIM_POINTS, 1, grid_size.
x * grid_size.
y * grid_size.
z);
600 debug_data_tx.ensure_3d(
601 gpu::TextureFormat::SFLOAT_16_16_16_16, grid_size, usage,
data);
606 debug_ps_.bind_texture(
"debug_data_tx", debug_data_tx);
607 debug_ps_.draw_procedural(
611 inst_.manager->submit(debug_ps_,
view);
623 if (!display_grids_enabled_) {
627 for (
const VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
628 if (!grid.viewport_display || grid.viewport_display_size == 0.0f || !grid.cache ||
629 !grid.cache->grid_static_cache)
646 irradiance_a_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16_16,
650 irradiance_b_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16_16,
654 irradiance_c_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16_16,
658 irradiance_d_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16_16,
662 validity_tx.ensure_3d(
663 gpu::TextureFormat::SFLOAT_16, grid_size, usage, (
const float *)cache->
baking.
validity);
666 validity_tx.clear(
float4(0.0));
670 irradiance_a_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
674 irradiance_b_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
678 irradiance_c_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
682 irradiance_d_tx.ensure_3d(gpu::TextureFormat::SFLOAT_16_16_16,
686 validity_tx.ensure_3d(gpu::TextureFormat::UNORM_8, grid_size, usage);
699 validity_tx.clear(
float4(0.0));
706 display_grids_ps_.init();
710 display_grids_ps_.framebuffer_set(&view_fb);
711 display_grids_ps_.shader_set(inst_.shaders.static_shader_get(DISPLAY_PROBE_VOLUME));
713 display_grids_ps_.push_constant(
"sphere_radius", grid.viewport_display_size);
714 display_grids_ps_.push_constant(
"grid_resolution", grid_size);
715 display_grids_ps_.push_constant(
"grid_to_world", grid.object_to_world);
716 display_grids_ps_.push_constant(
"world_to_grid", grid.world_to_object);
718 display_grids_ps_.push_constant(
"display_validity",
false);
720 display_grids_ps_.bind_texture(
"irradiance_a_tx", &irradiance_a_tx);
721 display_grids_ps_.bind_texture(
"irradiance_b_tx", &irradiance_b_tx);
722 display_grids_ps_.bind_texture(
"irradiance_c_tx", &irradiance_c_tx);
723 display_grids_ps_.bind_texture(
"irradiance_d_tx", &irradiance_d_tx);
724 display_grids_ps_.bind_texture(
"validity_tx", &validity_tx);
727 int triangle_count = sample_count * 2;
728 display_grids_ps_.draw_procedural(
GPU_PRIM_TRIS, 1, triangle_count * 3);
730 inst_.manager->submit(display_grids_ps_,
view);
732 irradiance_a_tx.free();
733 irradiance_b_tx.free();
734 irradiance_c_tx.free();
735 irradiance_d_tx.free();
750 surfel_density_ = lightprobe.grid_surfel_density / max_axis_len;
751 min_distance_to_surface_ = lightprobe.grid_surface_bias;
752 max_virtual_offset_ = lightprobe.grid_escape_bias;
753 clip_distance_ = lightprobe.clipend;
779 pass.
dispatch(&dispatch_per_surfel_);
787 pass.
bind_image(
"cluster_list_img", &cluster_list_tx_);
789 pass.
dispatch(&dispatch_per_surfel_);
801 sub.
bind_ssbo(
"list_counter_buf", &list_counter_buf_);
802 sub.
bind_ssbo(
"list_info_buf", &list_info_buf_);
804 sub.
dispatch(&dispatch_per_surfel_);
812 sub.
bind_ssbo(
"list_counter_buf", &list_counter_buf_);
813 sub.
bind_ssbo(
"list_range_buf", &list_range_buf_);
814 sub.
bind_ssbo(
"list_info_buf", &list_info_buf_);
825 sub.
bind_ssbo(
"list_counter_buf", &list_counter_buf_);
826 sub.
bind_ssbo(
"list_range_buf", &list_range_buf_);
827 sub.
bind_ssbo(
"list_item_distance_buf", &list_item_distance_buf_);
828 sub.
bind_ssbo(
"list_item_surfel_id_buf", &list_item_surfel_id_buf_);
829 sub.
bind_ssbo(
"list_info_buf", &list_info_buf_);
831 sub.
dispatch(&dispatch_per_surfel_);
839 sub.
bind_ssbo(
"list_range_buf", &list_range_buf_);
840 sub.
bind_ssbo(
"list_item_surfel_id_buf", &list_item_surfel_id_buf_);
841 sub.
bind_ssbo(
"list_item_distance_buf", &list_item_distance_buf_);
842 sub.
bind_ssbo(
"sorted_surfel_id_buf", &sorted_surfel_id_buf_);
843 sub.
bind_ssbo(
"list_info_buf", &list_info_buf_);
845 sub.
dispatch(&dispatch_per_surfel_);
854 sub.
bind_ssbo(
"list_start_buf", &list_start_buf_);
855 sub.
bind_ssbo(
"list_range_buf", &list_range_buf_);
856 sub.
bind_ssbo(
"sorted_surfel_id_buf", &sorted_surfel_id_buf_);
857 sub.
bind_ssbo(
"list_info_buf", &list_info_buf_);
863 PassSimple &pass = surfel_light_propagate_ps_;
874 sub.
dispatch(&dispatch_per_surfel_);
884 pass.
bind_ssbo(
"list_start_buf", &list_start_buf_);
885 pass.
bind_ssbo(
"list_info_buf", &list_info_buf_);
887 pass.
bind_image(
"irradiance_L0_img", &irradiance_L0_tx_);
888 pass.
bind_image(
"irradiance_L1_a_img", &irradiance_L1_a_tx_);
889 pass.
bind_image(
"irradiance_L1_b_img", &irradiance_L1_b_tx_);
890 pass.
bind_image(
"irradiance_L1_c_img", &irradiance_L1_c_tx_);
891 pass.
bind_image(
"validity_img", &validity_tx_);
892 pass.
bind_image(
"virtual_offset_img", &virtual_offset_tx_);
894 pass.
dispatch(&dispatch_per_grid_sample_);
902 pass.
bind_ssbo(
"list_start_buf", &list_start_buf_);
903 pass.
bind_ssbo(
"list_info_buf", &list_info_buf_);
904 pass.
bind_image(
"cluster_list_img", &cluster_list_tx_);
905 pass.
bind_image(
"virtual_offset_img", &virtual_offset_tx_);
907 pass.
dispatch(&dispatch_per_grid_sample_);
927 for (
int x : {0, 1}) {
928 for (
int y : {0, 1}) {
929 for (
int z : {0, 1}) {
930 float3 ws_corner = scene_min + ((scene_max - scene_min) *
float3(
x,
y,
z));
932 extent_min =
min(extent_min, ls_corner);
933 extent_max =
max(extent_max, ls_corner);
939 extent_min =
max(extent_min, -target_extent);
940 extent_max =
min(extent_max, target_extent);
942 grid_pixel_extent_ =
max(
int3(1),
int3(surfel_density_ * (extent_max - extent_min)));
943 grid_pixel_extent_ =
min(grid_pixel_extent_,
int3(16384));
947 distance(extent_min, extent_max) / 2.0f);
958 capture_extent_max.x,
959 capture_extent_min.y,
960 capture_extent_max.y,
961 -capture_extent_min.z,
962 -capture_extent_max.z);
964 view.visibility_test(
false);
965 view.sync(
invert(capture_viewinv), capture_winmat);
968 sync_view(view_x_, basis_x_);
969 sync_view(view_y_, basis_y_);
970 sync_view(view_z_, basis_z_);
984 int3 grid_resolution =
int3(&lightprobe.grid_resolution_x);
985 float4x4 grid_local_to_world =
invert(probe_object.world_to_object());
989 capture_info_buf_.capture_world_direct = capture_world_;
990 capture_info_buf_.capture_world_indirect = capture_world_ && capture_indirect_;
991 capture_info_buf_.capture_visibility_direct = !capture_world_;
992 capture_info_buf_.capture_visibility_indirect = !(capture_world_ && capture_indirect_);
993 capture_info_buf_.capture_indirect = capture_indirect_;
994 capture_info_buf_.capture_emission = capture_emission_;
998 capture_info_buf_.world_atlas_coord = world_data.
atlas_coord;
1001 capture_info_buf_.irradiance_grid_size = grid_resolution;
1002 capture_info_buf_.irradiance_grid_local_to_world = grid_local_to_world;
1003 capture_info_buf_.irradiance_grid_world_to_local = probe_object.world_to_object();
1004 capture_info_buf_.irradiance_grid_world_to_local_rotation =
float4x4(
1007 capture_info_buf_.min_distance_to_surface = min_distance_to_surface_;
1008 capture_info_buf_.max_virtual_offset = max_virtual_offset_;
1009 capture_info_buf_.surfel_radius = 0.5f / surfel_density_;
1012 capture_info_buf_.min_distance_to_surface *= min_distance_between_grid_samples;
1013 capture_info_buf_.max_virtual_offset *= min_distance_between_grid_samples;
1014 capture_info_buf_.clamp_direct = (lightprobe.grid_clamp_direct > 0.0) ?
1015 lightprobe.grid_clamp_direct :
1017 capture_info_buf_.clamp_indirect = (lightprobe.grid_clamp_indirect > 0.0) ?
1018 lightprobe.grid_clamp_indirect :
1026 irradiance_L0_tx_.ensure_3d(
1027 gpu::TextureFormat::SFLOAT_32_32_32_32, grid_resolution, texture_usage);
1028 irradiance_L1_a_tx_.ensure_3d(
1029 gpu::TextureFormat::SFLOAT_32_32_32_32, grid_resolution, texture_usage);
1030 irradiance_L1_b_tx_.ensure_3d(
1031 gpu::TextureFormat::SFLOAT_32_32_32_32, grid_resolution, texture_usage);
1032 irradiance_L1_c_tx_.ensure_3d(
1033 gpu::TextureFormat::SFLOAT_32_32_32_32, grid_resolution, texture_usage);
1034 validity_tx_.ensure_3d(gpu::TextureFormat::SFLOAT_32, grid_resolution, texture_usage);
1035 virtual_offset_tx_.ensure_3d(
1036 gpu::TextureFormat::SFLOAT_16_16_16_16, grid_resolution, texture_usage);
1038 if (!irradiance_L0_tx_.is_valid() || !irradiance_L1_a_tx_.is_valid() ||
1039 !irradiance_L1_b_tx_.is_valid() || !irradiance_L1_c_tx_.is_valid() ||
1040 !validity_tx_.is_valid() || !virtual_offset_tx_.is_valid())
1042 inst_.info_append_i18n(
"Error: Not enough memory to bake {}.", probe_object.
id.
name);
1047 irradiance_L0_tx_.clear(
float4(0.0f));
1048 irradiance_L1_a_tx_.clear(
float4(0.0f));
1049 irradiance_L1_b_tx_.clear(
float4(0.0f));
1050 irradiance_L1_c_tx_.clear(
float4(0.0f));
1051 validity_tx_.clear(
float4(0.0f));
1052 virtual_offset_tx_.clear(
float4(0.0f));
1061 pass.
bind_ssbo(
"capture_info_buf", &capture_info_buf_);
1069 capture_info_buf_.do_surfel_count =
false;
1070 capture_info_buf_.do_surfel_output =
false;
1072 const int neg_flt_max = int(0xFF7FFFFFu ^ 0x7FFFFFFFu);
1073 const int pos_flt_max = 0x7F7FFFFF;
1074 capture_info_buf_.scene_bound_x_min = pos_flt_max;
1075 capture_info_buf_.scene_bound_y_min = pos_flt_max;
1076 capture_info_buf_.scene_bound_z_min = pos_flt_max;
1077 capture_info_buf_.scene_bound_x_max = neg_flt_max;
1078 capture_info_buf_.scene_bound_y_max = neg_flt_max;
1079 capture_info_buf_.scene_bound_z_max = neg_flt_max;
1081 capture_info_buf_.push_update();
1083 inst_.manager->submit(irradiance_bounds_ps_);
1086 capture_info_buf_.read();
1088 if (capture_info_buf_.scene_bound_x_min == pos_flt_max) {
1094 auto ordered_int_bits_to_float = [](
int32_t int_value) ->
float {
1095 int32_t float_bits = (int_value < 0) ? (int_value ^ 0x7FFFFFFF) : int_value;
1096 return *
reinterpret_cast<float *
>(&float_bits);
1099 float3 scene_min =
float3(ordered_int_bits_to_float(capture_info_buf_.scene_bound_x_min),
1100 ordered_int_bits_to_float(capture_info_buf_.scene_bound_y_min),
1101 ordered_int_bits_to_float(capture_info_buf_.scene_bound_z_min));
1102 float3 scene_max =
float3(ordered_int_bits_to_float(capture_info_buf_.scene_bound_x_max),
1103 ordered_int_bits_to_float(capture_info_buf_.scene_bound_y_max),
1104 ordered_int_bits_to_float(capture_info_buf_.scene_bound_z_max));
1106 float epsilon = 1.0f / surfel_density_;
1107 scene_min -= epsilon;
1108 scene_max += epsilon;
1114 inst_.camera.sync();
1117 inst_.shadows.end_sync();
1118 inst_.lights.end_sync();
1123 capture_info_buf_.do_surfel_count =
true;
1124 capture_info_buf_.do_surfel_output =
false;
1125 capture_info_buf_.surfel_len = 0u;
1126 capture_info_buf_.push_update();
1129 inst_.pipelines.capture.render(view_x_);
1131 inst_.pipelines.capture.render(view_y_);
1133 inst_.pipelines.capture.render(view_z_);
1139 capture_info_buf_.read();
1140 if (capture_info_buf_.surfel_len == 0) {
1145 if (capture_info_buf_.surfel_len > surfels_buf_.size()) {
1147 &
Instance::log,
"IrradianceBake: Allocating %u surfels.", capture_info_buf_.surfel_len);
1151 int total_mem_kb, free_mem_kb;
1155 size_t max_alloc = (size_t(total_mem_kb) - 128 * 1024) * 1024;
1157 size_t max_free = size_t((
size_t(free_mem_kb) * 1024) * 0.95f);
1159 max_size =
min(max_size,
min(max_alloc, max_free));
1162 size_t required_mem =
sizeof(
Surfel) * (capture_info_buf_.surfel_len - surfels_buf_.size());
1163 if (required_mem > max_size) {
1165 const uint req_mb = required_mem / (1024 * 1024);
1166 const uint max_mb = max_size / (1024 * 1024);
1168 if (is_ssbo_bound) {
1169 inst_.info_append_i18n(
1170 "Cannot allocate enough video memory to bake \"{}\" ({} / {} MBytes).\n"
1171 "Try reducing surfel resolution or capture distance to lower the size of the "
1178 inst_.info_append_i18n(
1179 "Not enough available video memory to bake \"{}\" ({} / {} MBytes).\n"
1180 "Try reducing surfel resolution or capture distance to lower the size of the "
1189 fprintf(stderr,
"%s", inst_.info_get());
1197 surfels_buf_.resize(capture_info_buf_.surfel_len);
1198 surfels_buf_.clear_to_zero();
1205 capture_info_buf_.do_surfel_count =
true;
1206 capture_info_buf_.do_surfel_output =
true;
1207 capture_info_buf_.surfel_len = 0u;
1208 capture_info_buf_.push_update();
1211 inst_.pipelines.capture.render(view_x_);
1213 inst_.pipelines.capture.render(view_y_);
1215 inst_.pipelines.capture.render(view_z_);
1220 capture_info_buf_.read();
1229 inst_.render_buffers.acquire(
int2(1));
1230 inst_.hiz_buffer.set_source(&inst_.render_buffers.depth_tx);
1231 inst_.lights.set_view(view_z_, grid_pixel_extent_.xy());
1232 inst_.shadows.set_view(view_z_, grid_pixel_extent_.xy());
1239 inst_.render_buffers.release();
1241 inst_.manager->submit(surfel_light_eval_ps_, view_z_);
1246 if (max_virtual_offset_ == 0.0f) {
1252 cluster_list_tx_.ensure_3d(
1253 gpu::TextureFormat::SINT_32, capture_info_buf_.irradiance_grid_size, texture_usage);
1254 cluster_list_tx_.clear(
int4(-1));
1256 inst_.manager->submit(surfel_cluster_build_ps_, view_z_);
1261 if (max_virtual_offset_ == 0.0f) {
1266 inst_.manager->submit(irradiance_offset_ps_, view_z_);
1269 cluster_list_tx_.free();
1278 const float3 up = ray_direction;
1286 min -= scene_bound_sphere_.w;
1287 max += scene_bound_sphere_.w;
1301 const float max_distance_between_neighbor_surfels_inv =
M_SQRT1_2 - 1
e-4;
1303 const float ray_grid_density = surfel_density_ * max_distance_between_neighbor_surfels_inv;
1305 const float pixel_size = 1.0f / ray_grid_density;
1311 list_info_buf_.ray_grid_size +=
int2(4);
1312 min -= pixel_size * 2.0f;
1313 max += pixel_size * 2.0f;
1318 const float2 aa_offset = (aa_rand - 0.5f) * 0.499f;
1319 min += pixel_size * aa_offset;
1321 list_info_buf_.list_max = list_info_buf_.ray_grid_size.x * list_info_buf_.ray_grid_size.y;
1322 list_info_buf_.push_update();
1327 ray_view_.sync(viewmat, winmat);
1343 inst_.manager->submit(surfel_ray_build_ps_, ray_view_);
1349 capture_info_buf_.sample_index = inst_.sampling.sample_index() - 1;
1350 capture_info_buf_.sample_count = inst_.sampling.sample_count();
1351 capture_info_buf_.push_update();
1353 inst_.manager->submit(surfel_light_propagate_ps_, ray_view_);
1355 std::swap(radiance_src_, radiance_dst_);
1360 inst_.manager->submit(irradiance_capture_ps_, ray_view_);
1365 if (!
ELEM(inst_.debug_mode,
1375 capture_info_buf_.read();
1376 surfels_buf_.read();
1378 cache_frame->
surfels_len = capture_info_buf_.surfel_len;
1383 surfels_dst.copy_from(surfels_src);
1388 if (!
ELEM(inst_.debug_mode, eDebugMode::DEBUG_IRRADIANCE_CACHE_VIRTUAL_OFFSET)) {
1402 read_surfels(cache_frame);
1403 read_virtual_offset(cache_frame);
1405 cache_frame->
size[0] = irradiance_L0_tx_.width();
1406 cache_frame->
size[1] = irradiance_L0_tx_.height();
1407 cache_frame->
size[2] = irradiance_L0_tx_.depth();
1424 read_surfels(cache_frame);
1425 read_virtual_offset(cache_frame);
1427 cache_frame->
size[0] = irradiance_L0_tx_.width();
1428 cache_frame->
size[1] = irradiance_L0_tx_.height();
1429 cache_frame->
size[2] = irradiance_L0_tx_.depth();
1439 int64_t sample_count =
int64_t(irradiance_L0_tx_.width()) * irradiance_L0_tx_.height() *
1440 irradiance_L0_tx_.depth();
1441 size_t coefficient_texture_size =
sizeof(*cache_frame->
irradiance.
L0) * sample_count;
1449 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 int max_ii(int a, int b)
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define CLOG_INFO(clg_ref,...)
struct LightProbeGridCacheFrame LightProbeGridCacheFrame
@ LIGHTPROBE_GRID_CAPTURE_EMISSION
@ LIGHTPROBE_GRID_CAPTURE_WORLD
@ LIGHTPROBE_GRID_CAPTURE_INDIRECT
T & DRW_object_get_data_for_drawing(const Object &object)
static void View(GHOST_IWindow *window, bool stereo, int eye=0)
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_debug_group_end()
void GPU_debug_group_begin(const char *name)
@ GPU_BARRIER_SHADER_STORAGE
@ GPU_BARRIER_TEXTURE_FETCH
@ GPU_BARRIER_BUFFER_UPDATE
@ GPU_BARRIER_SHADER_IMAGE_ACCESS
@ GPU_BARRIER_TEXTURE_UPDATE
void GPU_memory_barrier(GPUBarrier barrier)
void GPU_storagebuf_clear(blender::gpu::StorageBuf *ssbo, uint32_t clear_value)
void GPU_texture_swizzle_set(blender::gpu::Texture *texture, const char swizzle[4])
void GPU_texture_update_sub(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_HOST_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_TEXTURE_USAGE_ATOMIC
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
constexpr void copy_from(Span< T > values) const
void append(const T &value)
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 bind_resources(U &resources)
void shader_set(gpu::Shader *shader)
void bind_texture(const char *name, gpu::Texture *texture, GPUSamplerState state=sampler_auto)
void bind_image(const char *name, gpu::Texture *image)
PassBase< DrawCommandBufType > & sub(const char *name)
void dispatch(int group_len)
void barrier(GPUBarrier type)
void push_constant(const char *name, const float &data)
void bind_ssbo(const char *name, gpu::StorageBuf *buffer)
detail::PassBase< command::DrawCommandBuf > Sub
void init(const Object &probe_object)
void surfels_lights_eval()
void irradiance_capture()
LightProbeGridCacheFrame * read_result_packed()
LightProbeGridCacheFrame * read_result_unpacked()
void surfels_create(const Object &probe_object)
void surfel_raster_views_sync(const float3 &scene_min, const float3 &scene_max, const float4x4 &probe_to_world)
static float3 sample_sphere(const float2 &rand)
void set_view(View &view)
Vector< IrradianceBrickPacked > bricks_alloc(int brick_len)
void bricks_free(Vector< IrradianceBrickPacked > &bricks)
void viewport_draw(View &view, gpu::FrameBuffer *view_fb)
@ DRW_STATE_CLIP_CONTROL_UNIT_RANGE
#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
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
float distance(VecOp< float, D >, VecOp< float, D >) RET
BLI_INLINE void grid_to_world(HairGrid *grid, float vecw[3], const float vec[3])
CCL_NAMESPACE_BEGIN ccl_device float invert(const float color, const float factor)
void * MEM_mallocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
detail::Pass< command::DrawCommandBuf > PassSimple
@ LIGHTPROBE_IRRADIANCE_RAY
@ LIGHTPROBE_IRRADIANCE_LOAD
@ LIGHTPROBE_IRRADIANCE_OFFSET
@ LIGHTPROBE_IRRADIANCE_WORLD
@ LIGHTPROBE_IRRADIANCE_BOUNDS
static IrradianceBrickPacked irradiance_brick_pack(IrradianceBrick brick)
@ DEBUG_IRRADIANCE_CACHE_SURFELS_VISIBILITY
@ DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE
@ DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL
@ DEBUG_IRRADIANCE_CACHE_VIRTUAL_OFFSET
@ DEBUG_IRRADIANCE_CACHE_VALIDITY
@ DEBUG_IRRADIANCE_CACHE_SURFELS_CLUSTER
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 ...
QuaternionBase< float > Quaternion
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
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 reduce_min(const VecBase< T, Size > &a)
T min(const T &a, const T &b)
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)
VecBase< T, 3 > orthogonal(const VecBase< T, 3 > &v)
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)
CartesianBasis from_orthonormal_axes(const AxisSigned forward, const AxisSigned up)
MatT from_rotation(const RotationT &rotation)
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &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< float, 2 > float2
VecBase< int32_t, 3 > int3
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
float(* virtual_offset)[4]
LightProbeVisibilityData visibility
LightProbeBakingData baking
LightProbeConnectivityData connectivity
LightProbeIrradianceData irradiance
static MatBase identity()
VecBase< T, 2 > xy() const
SphereProbeUvArea atlas_coord
float3x4 world_to_grid_transposed
packed_int3 grid_size_padded