28 display_grids_enabled_ = inst_.draw_overlays;
31 bool use_l2_band =
false;
32 int sh_coef_len = use_l2_band ? 9 : 4;
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;
71 if (irradiance_atlas_tx_.is_valid()) {
72 do_full_update_ =
true;
73 irradiance_pool_size_alloc_ = irradiance_pool_size;
74 atlas_col_count = atlas_col_count_try;
79 if (irradiance_pool_size_alloc_ != irradiance_pool_size_) {
80 inst_.info_append_i18n(
81 "Warning: Could not allocate light probes volume pool of {} MB, using {} MB instead.",
82 irradiance_pool_size_,
83 irradiance_pool_size_alloc_);
86 if (do_full_update_) {
87 do_full_update_ =
false;
88 do_update_world_ =
true;
91 for (
VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
96 for (
auto i :
IndexRange(atlas_row_count * atlas_col_count)) {
99 world_brick_index_ = 0;
109 if (irradiance_atlas_tx_.is_valid()) {
111 irradiance_atlas_tx_.clear(
float4(0.0f));
115 if (irradiance_atlas_tx_.is_valid() ==
false) {
116 inst_.info_append_i18n(
"Irradiance Atlas texture could not be created");
122 if (inst_.is_baking()) {
129 if (brick_pool_.size() < brick_len) {
135 allocated.
as_mutable_span().copy_from(brick_pool_.as_span().take_back(brick_len));
137 brick_pool_.resize(brick_pool_.size() - brick_len);
152 bool any_update =
false;
154 bricks_infos_buf_.
clear();
155 for (
VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
157 if (cache ==
nullptr) {
167 if (grid_size.x <= 0 || grid_size.y <= 0 || grid_size.z <= 0) {
168 inst_.info_append_i18n(
"Error: Malformed irradiance grid data");
176 inst_.info_append_i18n(
"Error: Too many irradiance grids in the scene");
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()) {
190 inst_.info_append_i18n(
"Error: Irradiance grid allocation failed");
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;
241 float3 _b =
b->object_to_world.location();
258 grid->grid_index = grids_len;
259 grids_infos_buf_[grids_len++] = *grid;
263 world_grid_index = grids_len++;
272 grids_infos_buf_[world_grid_index] = grid;
274 bricks_infos_buf_.append(world_brick_index_);
278 grids_infos_buf_[grids_len].grid_size_padded =
int3(-1);
281 bricks_infos_buf_.push_update();
282 grids_infos_buf_.push_update();
286 if (do_update_world_) {
287 grid_upload_ps_.init();
289 grid_upload_ps_.bind_resources(inst_.uniform_data);
290 grid_upload_ps_.bind_ssbo(
"harmonic_buf", &inst_.sphere_probes.spherical_harmonics_buf());
291 grid_upload_ps_.bind_ubo(
"grids_infos_buf", &grids_infos_buf_);
292 grid_upload_ps_.bind_ssbo(
"bricks_infos_buf", &bricks_infos_buf_);
293 grid_upload_ps_.push_constant(
"grid_index", world_grid_index);
294 grid_upload_ps_.bind_image(
"irradiance_atlas_img", &irradiance_atlas_tx_);
298 grid_upload_ps_.dispatch(
int3(1));
302 inst_.manager->submit(grid_upload_ps_);
308 int grid_start_index = grid_loaded.size() + 1;
309 for (
auto it = grid_loaded.rbegin(); it != grid_loaded.rend(); ++it) {
312 VolumeProbe *grid = *it;
313 if (!grid->do_update) {
317 grid->do_update =
false;
322 draw::Texture irradiance_a_tx = {
"irradiance_a_tx"};
323 draw::Texture irradiance_b_tx = {
"irradiance_b_tx"};
324 draw::Texture irradiance_c_tx = {
"irradiance_c_tx"};
325 draw::Texture irradiance_d_tx = {
"irradiance_d_tx"};
326 draw::Texture validity_tx = {
"validity_tx"};
338 validity_tx.clear(
float4(0.0));
343 irradiance_b_tx.ensure_3d(
345 irradiance_c_tx.ensure_3d(
347 irradiance_d_tx.ensure_3d(
349 validity_tx.ensure_3d(
GPU_R8, grid_size, usage);
362 validity_tx.clear(
float4(0.0));
369 if (irradiance_a_tx.is_valid() ==
false) {
370 inst_.info_append_i18n(
"Error: Could not allocate irradiance staging texture");
380 bool visibility_available = cache->
visibility.
L0 !=
nullptr;
383 draw::Texture visibility_a_tx = {
"visibility_a_tx"};
384 draw::Texture visibility_b_tx = {
"visibility_b_tx"};
385 draw::Texture visibility_c_tx = {
"visibility_c_tx"};
386 draw::Texture visibility_d_tx = {
"visibility_d_tx"};
387 if (visibility_available) {
398 else if (!is_baking) {
406 grid_upload_ps_.init();
409 grid_upload_ps_.bind_resources(inst_.uniform_data);
410 grid_upload_ps_.push_constant(
"validity_threshold", grid->validity_threshold);
411 grid_upload_ps_.push_constant(
"dilation_threshold", grid->dilation_threshold);
412 grid_upload_ps_.push_constant(
"dilation_radius", grid->dilation_radius);
413 grid_upload_ps_.push_constant(
"grid_index", grid->grid_index);
414 grid_upload_ps_.push_constant(
"grid_start_index", grid_start_index);
415 grid_upload_ps_.push_constant(
"grid_local_to_world", grid->object_to_world);
416 grid_upload_ps_.push_constant(
"grid_intensity_factor", grid->intensity);
417 grid_upload_ps_.bind_ubo(
"grids_infos_buf", &grids_infos_buf_);
418 grid_upload_ps_.bind_ssbo(
"bricks_infos_buf", &bricks_infos_buf_);
419 grid_upload_ps_.bind_texture(
"irradiance_a_tx", &irradiance_a_tx);
420 grid_upload_ps_.bind_texture(
"irradiance_b_tx", &irradiance_b_tx);
421 grid_upload_ps_.bind_texture(
"irradiance_c_tx", &irradiance_c_tx);
422 grid_upload_ps_.bind_texture(
"irradiance_d_tx", &irradiance_d_tx);
423 grid_upload_ps_.bind_texture(
"validity_tx", &validity_tx);
424 grid_upload_ps_.bind_image(
"irradiance_atlas_img", &irradiance_atlas_tx_);
427 grid_upload_ps_.bind_texture(
"irradiance_atlas_tx", &irradiance_atlas_tx_);
430 bool use_vis = visibility_available;
431 grid_upload_ps_.bind_texture(
"visibility_a_tx", use_vis ? &visibility_a_tx : &irradiance_a_tx);
432 grid_upload_ps_.bind_texture(
"visibility_b_tx", use_vis ? &visibility_b_tx : &irradiance_b_tx);
433 grid_upload_ps_.bind_texture(
"visibility_c_tx", use_vis ? &visibility_c_tx : &irradiance_c_tx);
434 grid_upload_ps_.bind_texture(
"visibility_d_tx", use_vis ? &visibility_d_tx : &irradiance_d_tx);
437 int3 grid_size_with_padding = grid_size + 2;
441 grid_upload_ps_.dispatch(grid_size_in_bricks);
445 inst_.manager->submit(grid_upload_ps_);
447 irradiance_a_tx.free();
448 irradiance_b_tx.free();
449 irradiance_c_tx.free();
450 irradiance_d_tx.free();
453 do_update_world_ =
false;
458 if (!inst_.is_baking()) {
459 debug_pass_draw(
view, view_fb);
460 display_pass_draw(
view, view_fb);
464void VolumeProbeModule::debug_pass_draw(
View &
view, GPUFrameBuffer *view_fb)
466 switch (inst_.debug_mode) {
468 inst_.info_append(
"Debug Mode: Surfels Normal");
471 inst_.info_append(
"Debug Mode: Surfels Cluster");
474 inst_.info_append(
"Debug Mode: Surfels Irradiance");
477 inst_.info_append(
"Debug Mode: Surfels Visibility");
480 inst_.info_append(
"Debug Mode: Irradiance Validity");
483 inst_.info_append(
"Debug Mode: Virtual Offset");
490 for (
const VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
491 if (grid.cache ==
nullptr) {
497 if (cache ==
nullptr) {
501 switch (inst_.debug_mode) {
502 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL:
503 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_CLUSTER:
504 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_VISIBILITY:
505 case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE: {
513 debug_ps_.framebuffer_set(&view_fb);
514 debug_ps_.shader_set(inst_.shaders.static_shader_get(DEBUG_SURFELS));
515 debug_ps_.push_constant(
"debug_surfel_radius", 0.5f * max_axis_len / grid.surfel_density);
516 debug_ps_.push_constant(
"debug_mode",
int(inst_.debug_mode));
523 debug_surfels_buf_.push_update();
525 debug_ps_.bind_ssbo(
"surfels_buf", debug_surfels_buf_);
528 inst_.manager->submit(debug_ps_,
view);
532 case eDebugMode::DEBUG_IRRADIANCE_CACHE_VALIDITY:
533 case eDebugMode::DEBUG_IRRADIANCE_CACHE_VIRTUAL_OFFSET: {
538 debug_ps_.framebuffer_set(&view_fb);
539 debug_ps_.shader_set(inst_.shaders.static_shader_get(DEBUG_IRRADIANCE_GRID));
540 debug_ps_.push_constant(
"debug_mode",
int(inst_.debug_mode));
541 debug_ps_.push_constant(
"grid_mat", grid.object_to_world);
544 Texture debug_data_tx = {
"debug_data_tx"};
546 if (inst_.debug_mode == eDebugMode::DEBUG_IRRADIANCE_CACHE_VALIDITY) {
550 debug_data_tx.ensure_3d(
GPU_R16F, grid_size, usage,
data);
553 debug_data_tx.ensure_3d(
GPU_R8, grid_size, usage);
566 debug_ps_.push_constant(
"debug_value", grid.validity_threshold);
567 debug_ps_.bind_texture(
"debug_data_tx", debug_data_tx);
568 debug_ps_.draw_procedural(
GPU_PRIM_POINTS, 1, grid_size.
x * grid_size.
y * grid_size.
z);
578 debug_ps_.bind_texture(
"debug_data_tx", debug_data_tx);
579 debug_ps_.draw_procedural(
583 inst_.manager->submit(debug_ps_,
view);
593void VolumeProbeModule::display_pass_draw(
View &
view, GPUFrameBuffer *view_fb)
595 if (!display_grids_enabled_) {
599 for (
const VolumeProbe &grid : inst_.light_probes.volume_map_.values()) {
600 if (!grid.viewport_display || grid.viewport_display_size == 0.0f || !grid.cache ||
601 !grid.cache->grid_static_cache)
625 validity_tx.clear(
float4(0.0));
630 irradiance_b_tx.ensure_3d(
632 irradiance_c_tx.ensure_3d(
634 irradiance_d_tx.ensure_3d(
636 validity_tx.ensure_3d(
GPU_R8, grid_size, usage);
649 validity_tx.clear(
float4(0.0));
656 display_grids_ps_.init();
660 display_grids_ps_.framebuffer_set(&view_fb);
661 display_grids_ps_.shader_set(inst_.shaders.static_shader_get(DISPLAY_PROBE_VOLUME));
663 display_grids_ps_.push_constant(
"sphere_radius", grid.viewport_display_size);
664 display_grids_ps_.push_constant(
"grid_resolution", grid_size);
665 display_grids_ps_.push_constant(
"grid_to_world", grid.object_to_world);
666 display_grids_ps_.push_constant(
"world_to_grid", grid.world_to_object);
668 display_grids_ps_.push_constant(
"display_validity",
false);
670 display_grids_ps_.bind_texture(
"irradiance_a_tx", &irradiance_a_tx);
671 display_grids_ps_.bind_texture(
"irradiance_b_tx", &irradiance_b_tx);
672 display_grids_ps_.bind_texture(
"irradiance_c_tx", &irradiance_c_tx);
673 display_grids_ps_.bind_texture(
"irradiance_d_tx", &irradiance_d_tx);
674 display_grids_ps_.bind_texture(
"validity_tx", &validity_tx);
677 int triangle_count = sample_count * 2;
678 display_grids_ps_.draw_procedural(
GPU_PRIM_TRIS, 1, triangle_count * 3);
680 inst_.manager->submit(display_grids_ps_,
view);
682 irradiance_a_tx.free();
683 irradiance_b_tx.free();
684 irradiance_c_tx.free();
685 irradiance_d_tx.free();
700 surfel_density_ = lightprobe.grid_surfel_density / max_axis_len;
701 min_distance_to_surface_ = lightprobe.grid_surface_bias;
702 max_virtual_offset_ = lightprobe.grid_escape_bias;
703 clip_distance_ = lightprobe.clipend;
729 pass.
dispatch(&dispatch_per_surfel_);
737 pass.
bind_image(
"cluster_list_img", &cluster_list_tx_);
739 pass.
dispatch(&dispatch_per_surfel_);
750 sub.
bind_ssbo(
"list_start_buf", &list_start_buf_);
751 sub.
bind_ssbo(
"list_info_buf", &list_info_buf_);
753 sub.
dispatch(&dispatch_per_surfel_);
760 sub.
bind_ssbo(
"list_start_buf", &list_start_buf_);
761 sub.
bind_ssbo(
"list_info_buf", &list_info_buf_);
767 PassSimple &pass = surfel_light_propagate_ps_;
778 sub.
dispatch(&dispatch_per_surfel_);
788 pass.
bind_ssbo(
"list_start_buf", &list_start_buf_);
789 pass.
bind_ssbo(
"list_info_buf", &list_info_buf_);
791 pass.
bind_image(
"irradiance_L0_img", &irradiance_L0_tx_);
792 pass.
bind_image(
"irradiance_L1_a_img", &irradiance_L1_a_tx_);
793 pass.
bind_image(
"irradiance_L1_b_img", &irradiance_L1_b_tx_);
794 pass.
bind_image(
"irradiance_L1_c_img", &irradiance_L1_c_tx_);
795 pass.
bind_image(
"validity_img", &validity_tx_);
796 pass.
bind_image(
"virtual_offset_img", &virtual_offset_tx_);
798 pass.
dispatch(&dispatch_per_grid_sample_);
806 pass.
bind_ssbo(
"list_start_buf", &list_start_buf_);
807 pass.
bind_ssbo(
"list_info_buf", &list_info_buf_);
808 pass.
bind_image(
"cluster_list_img", &cluster_list_tx_);
809 pass.
bind_image(
"virtual_offset_img", &virtual_offset_tx_);
811 pass.
dispatch(&dispatch_per_grid_sample_);
831 for (
int x : {0, 1}) {
832 for (
int y : {0, 1}) {
833 for (
int z : {0, 1}) {
834 float3 ws_corner = scene_min + ((scene_max - scene_min) *
float3(
x,
y,
z));
836 extent_min =
min(extent_min, ls_corner);
837 extent_max =
max(extent_max, ls_corner);
843 extent_min =
max(extent_min, -target_extent);
844 extent_max =
min(extent_max, target_extent);
846 grid_pixel_extent_ =
max(
int3(1),
int3(surfel_density_ * (extent_max - extent_min)));
847 grid_pixel_extent_ =
min(grid_pixel_extent_,
int3(16384));
851 distance(extent_min, extent_max) / 2.0f);
862 capture_extent_max.x,
863 capture_extent_min.y,
864 capture_extent_max.y,
865 -capture_extent_min.z,
866 -capture_extent_max.z);
868 view.visibility_test(
false);
869 view.sync(
invert(capture_viewinv), capture_winmat);
872 sync_view(view_x_, basis_x_);
873 sync_view(view_y_, basis_y_);
874 sync_view(view_z_, basis_z_);
888 int3 grid_resolution =
int3(&lightprobe.grid_resolution_x);
889 float4x4 grid_local_to_world =
invert(probe_object.world_to_object());
893 capture_info_buf_.capture_world_direct = capture_world_;
894 capture_info_buf_.capture_world_indirect = capture_world_ && capture_indirect_;
895 capture_info_buf_.capture_visibility_direct = !capture_world_;
896 capture_info_buf_.capture_visibility_indirect = !(capture_world_ && capture_indirect_);
897 capture_info_buf_.capture_indirect = capture_indirect_;
898 capture_info_buf_.capture_emission = capture_emission_;
902 capture_info_buf_.world_atlas_coord = world_data.
atlas_coord;
905 capture_info_buf_.irradiance_grid_size = grid_resolution;
906 capture_info_buf_.irradiance_grid_local_to_world = grid_local_to_world;
907 capture_info_buf_.irradiance_grid_world_to_local = probe_object.world_to_object();
908 capture_info_buf_.irradiance_grid_world_to_local_rotation =
float4x4(
911 capture_info_buf_.min_distance_to_surface = min_distance_to_surface_;
912 capture_info_buf_.max_virtual_offset = max_virtual_offset_;
913 capture_info_buf_.surfel_radius = 0.5f / surfel_density_;
916 capture_info_buf_.min_distance_to_surface *= min_distance_between_grid_samples;
917 capture_info_buf_.max_virtual_offset *= min_distance_between_grid_samples;
918 capture_info_buf_.clamp_direct = (lightprobe.grid_clamp_direct > 0.0) ?
919 lightprobe.grid_clamp_direct :
921 capture_info_buf_.clamp_indirect = (lightprobe.grid_clamp_indirect > 0.0) ?
922 lightprobe.grid_clamp_indirect :
930 irradiance_L0_tx_.ensure_3d(
GPU_RGBA32F, grid_resolution, texture_usage);
931 irradiance_L1_a_tx_.ensure_3d(
GPU_RGBA32F, grid_resolution, texture_usage);
932 irradiance_L1_b_tx_.ensure_3d(
GPU_RGBA32F, grid_resolution, texture_usage);
933 irradiance_L1_c_tx_.ensure_3d(
GPU_RGBA32F, grid_resolution, texture_usage);
934 validity_tx_.ensure_3d(
GPU_R32F, grid_resolution, texture_usage);
935 virtual_offset_tx_.ensure_3d(
GPU_RGBA16F, grid_resolution, texture_usage);
937 if (!irradiance_L0_tx_.is_valid() || !irradiance_L1_a_tx_.is_valid() ||
938 !irradiance_L1_b_tx_.is_valid() || !irradiance_L1_c_tx_.is_valid() ||
939 !validity_tx_.is_valid() || !virtual_offset_tx_.is_valid())
941 inst_.info_append_i18n(
"Error: Not enough memory to bake {}.", probe_object.
id.
name);
946 irradiance_L0_tx_.clear(
float4(0.0f));
947 irradiance_L1_a_tx_.clear(
float4(0.0f));
948 irradiance_L1_b_tx_.clear(
float4(0.0f));
949 irradiance_L1_c_tx_.clear(
float4(0.0f));
950 validity_tx_.clear(
float4(0.0f));
951 virtual_offset_tx_.clear(
float4(0.0f));
960 pass.
bind_ssbo(
"capture_info_buf", &capture_info_buf_);
968 capture_info_buf_.do_surfel_count =
false;
969 capture_info_buf_.do_surfel_output =
false;
971 const int neg_flt_max = int(0xFF7FFFFFu ^ 0x7FFFFFFFu);
972 const int pos_flt_max = 0x7F7FFFFF;
973 capture_info_buf_.scene_bound_x_min = pos_flt_max;
974 capture_info_buf_.scene_bound_y_min = pos_flt_max;
975 capture_info_buf_.scene_bound_z_min = pos_flt_max;
976 capture_info_buf_.scene_bound_x_max = neg_flt_max;
977 capture_info_buf_.scene_bound_y_max = neg_flt_max;
978 capture_info_buf_.scene_bound_z_max = neg_flt_max;
980 capture_info_buf_.push_update();
982 inst_.manager->submit(irradiance_bounds_ps_);
985 capture_info_buf_.read();
987 if (capture_info_buf_.scene_bound_x_min == pos_flt_max) {
993 auto ordered_int_bits_to_float = [](
int32_t int_value) ->
float {
994 int32_t float_bits = (int_value < 0) ? (int_value ^ 0x7FFFFFFF) : int_value;
995 return *
reinterpret_cast<float *
>(&float_bits);
998 float3 scene_min =
float3(ordered_int_bits_to_float(capture_info_buf_.scene_bound_x_min),
999 ordered_int_bits_to_float(capture_info_buf_.scene_bound_y_min),
1000 ordered_int_bits_to_float(capture_info_buf_.scene_bound_z_min));
1001 float3 scene_max =
float3(ordered_int_bits_to_float(capture_info_buf_.scene_bound_x_max),
1002 ordered_int_bits_to_float(capture_info_buf_.scene_bound_y_max),
1003 ordered_int_bits_to_float(capture_info_buf_.scene_bound_z_max));
1005 float epsilon = 1.0f / surfel_density_;
1006 scene_min -= epsilon;
1007 scene_max += epsilon;
1013 inst_.camera.sync();
1016 inst_.shadows.end_sync();
1017 inst_.lights.end_sync();
1022 capture_info_buf_.do_surfel_count =
true;
1023 capture_info_buf_.do_surfel_output =
false;
1024 capture_info_buf_.surfel_len = 0u;
1025 capture_info_buf_.push_update();
1028 inst_.pipelines.capture.render(view_x_);
1030 inst_.pipelines.capture.render(view_y_);
1032 inst_.pipelines.capture.render(view_z_);
1038 capture_info_buf_.read();
1039 if (capture_info_buf_.surfel_len == 0) {
1044 if (capture_info_buf_.surfel_len > surfels_buf_.size()) {
1045 printf(
"IrradianceBake: Allocating %u surfels.\n", capture_info_buf_.surfel_len);
1049 int total_mem_kb, free_mem_kb;
1053 size_t max_alloc = (size_t(total_mem_kb) - 128 * 1024) * 1024;
1055 size_t max_free = size_t((
size_t(free_mem_kb) * 1024) * 0.95f);
1057 max_size =
min(max_size,
min(max_alloc, max_free));
1060 size_t required_mem =
sizeof(
Surfel) * (capture_info_buf_.surfel_len - surfels_buf_.size());
1061 if (required_mem > max_size) {
1063 const uint req_mb = required_mem / (1024 * 1024);
1064 const uint max_mb = max_size / (1024 * 1024);
1066 if (is_ssbo_bound) {
1067 inst_.info_append_i18n(
1068 "Cannot allocate enough video memory to bake \"{}\" ({} / {} MBytes).\n"
1069 "Try reducing surfel resolution or capture distance to lower the size of the "
1076 inst_.info_append_i18n(
1077 "Not enough available video memory to bake \"{}\" ({} / {} MBytes).\n"
1078 "Try reducing surfel resolution or capture distance to lower the size of the "
1087 fprintf(stderr,
"%s", inst_.info_get());
1095 surfels_buf_.resize(capture_info_buf_.surfel_len);
1096 surfels_buf_.clear_to_zero();
1103 capture_info_buf_.do_surfel_count =
true;
1104 capture_info_buf_.do_surfel_output =
true;
1105 capture_info_buf_.surfel_len = 0u;
1106 capture_info_buf_.push_update();
1109 inst_.pipelines.capture.render(view_x_);
1111 inst_.pipelines.capture.render(view_y_);
1113 inst_.pipelines.capture.render(view_z_);
1118 capture_info_buf_.read();
1127 inst_.render_buffers.acquire(
int2(1));
1128 inst_.hiz_buffer.set_source(&inst_.render_buffers.depth_tx);
1129 inst_.lights.set_view(view_z_, grid_pixel_extent_.xy());
1130 inst_.shadows.set_view(view_z_, grid_pixel_extent_.xy());
1137 inst_.render_buffers.release();
1139 inst_.manager->submit(surfel_light_eval_ps_, view_z_);
1144 if (max_virtual_offset_ == 0.0f) {
1150 cluster_list_tx_.ensure_3d(
GPU_R32I, capture_info_buf_.irradiance_grid_size, texture_usage);
1151 cluster_list_tx_.clear(
int4(-1));
1153 inst_.manager->submit(surfel_cluster_build_ps_, view_z_);
1158 if (max_virtual_offset_ == 0.0f) {
1163 inst_.manager->submit(irradiance_offset_ps_, view_z_);
1166 cluster_list_tx_.free();
1175 const float3 up = ray_direction;
1183 min -= scene_bound_sphere_.w;
1184 max += scene_bound_sphere_.w;
1198 const float max_distance_between_neighbor_surfels_inv =
M_SQRT1_2 - 1
e-4;
1200 const float ray_grid_density = surfel_density_ * max_distance_between_neighbor_surfels_inv;
1202 const float pixel_size = 1.0f / ray_grid_density;
1208 list_info_buf_.ray_grid_size +=
int2(4);
1209 min -= pixel_size * 2.0f;
1210 max += pixel_size * 2.0f;
1215 const float2 aa_offset = (aa_rand - 0.5f) * 0.499f;
1216 min += pixel_size * aa_offset;
1218 list_info_buf_.list_max = list_info_buf_.ray_grid_size.x * list_info_buf_.ray_grid_size.y;
1219 list_info_buf_.push_update();
1224 ray_view_.sync(viewmat, winmat);
1231 inst_.manager->submit(surfel_ray_build_ps_, ray_view_);
1237 capture_info_buf_.sample_index = inst_.sampling.sample_index() - 1;
1238 capture_info_buf_.sample_count = inst_.sampling.sample_count();
1239 capture_info_buf_.push_update();
1241 inst_.manager->submit(surfel_light_propagate_ps_, ray_view_);
1243 std::swap(radiance_src_, radiance_dst_);
1248 inst_.manager->submit(irradiance_capture_ps_, ray_view_);
1253 if (!
ELEM(inst_.debug_mode,
1263 capture_info_buf_.read();
1264 surfels_buf_.read();
1266 cache_frame->
surfels_len = capture_info_buf_.surfel_len;
1271 surfels_dst.copy_from(surfels_src);
1276 if (!
ELEM(inst_.debug_mode, eDebugMode::DEBUG_IRRADIANCE_CACHE_VIRTUAL_OFFSET)) {
1290 read_surfels(cache_frame);
1291 read_virtual_offset(cache_frame);
1293 cache_frame->
size[0] = irradiance_L0_tx_.width();
1294 cache_frame->
size[1] = irradiance_L0_tx_.height();
1295 cache_frame->
size[2] = irradiance_L0_tx_.depth();
1312 read_surfels(cache_frame);
1313 read_virtual_offset(cache_frame);
1315 cache_frame->
size[0] = irradiance_L0_tx_.width();
1316 cache_frame->
size[1] = irradiance_L0_tx_.height();
1317 cache_frame->
size[2] = irradiance_L0_tx_.depth();
1327 int64_t sample_count =
int64_t(irradiance_L0_tx_.width()) * irradiance_L0_tx_.height() *
1328 irradiance_L0_tx_.depth();
1329 size_t coefficient_texture_size =
sizeof(*cache_frame->
irradiance.
L0) * sample_count;
1337 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
struct LightProbeGridCacheFrame LightProbeGridCacheFrame
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)
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])
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_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
void bind_resources(U &resources)
void bind_image(const char *name, GPUTexture *image)
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)
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, GPUFrameBuffer *view_fb)
Mesh & DRW_object_get_data_for_drawing(const Object &object)
@ 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
#define VOLUME_PROBE_FORMAT
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