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;
40 (
uint)inst_.scene->eevee.gi_irradiance_pool_size) ||
41 !irradiance_atlas_tx_.is_valid())
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_) {
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_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();
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++;
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);
283 bricks_infos_buf_.push_update();
284 grids_infos_buf_.push_update();
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;
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) {
471 inst_.info_append(
"Debug Mode: Surfels Normal");
474 inst_.info_append(
"Debug Mode: Surfels Cluster");
477 inst_.info_append(
"Debug Mode: Surfels Irradiance");
480 inst_.info_append(
"Debug Mode: Surfels Visibility");
483 inst_.info_append(
"Debug Mode: Irradiance Validity");
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));
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);
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)
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();
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;
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_);
790 pass.
bind_ssbo(
"list_start_buf", &list_start_buf_);
791 pass.
bind_ssbo(
"list_info_buf", &list_info_buf_);
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_);
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);
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);
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_);
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_);
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;
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();
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_);
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_);
1154 if (max_virtual_offset_ == 0.0f) {
1159 inst_.manager->submit(irradiance_offset_ps_, view_z_);
1162 cluster_list_tx_.free();
1170 const float3 ray_direction = inst_.sampling.sample_sphere(rand_uv);
1171 const float3 up = ray_direction;
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;
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();
1220 ray_view_.sync(viewmat, winmat);
1227 inst_.manager->submit(surfel_ray_build_ps_, ray_view_);
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_);
1244 inst_.manager->submit(irradiance_capture_ps_, ray_view_);
1249 if (!
ELEM(inst_.debug_mode,
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])
struct LightProbeGridCacheFrame LightProbeGridCacheFrame
@ LIGHTPROBE_GRID_CAPTURE_EMISSION
@ LIGHTPROBE_GRID_CAPTURE_WORLD
@ LIGHTPROBE_GRID_CAPTURE_INDIRECT
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_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])
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Texture
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.
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)
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)
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)
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 distance(float a, float b)
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