16 return instance_.scene->eevee.gi_cubemap_resolution / 2;
21 if (!instance_.is_viewport()) {
26 update_probes_this_sample_ = update_probes_next_sample_;
28 do_display_draw_ =
false;
33 LightProbeModule &light_probes = instance_.light_probes;
46 pass.
bind_ssbo(
"out_sh", &tmp_spherical_harmonics_);
47 pass.
bind_ssbo(
"out_sun", &tmp_sunlight_);
48 pass.
push_constant(
"probe_coord_packed",
reinterpret_cast<int4 *
>(&probe_sampling_coord_));
49 pass.
push_constant(
"write_coord_packed",
reinterpret_cast<int4 *
>(&probe_write_coord_));
52 pass.
dispatch(&dispatch_probe_pack_);
60 pass.
bind_image(
"out_atlas_mip_img", &convolve_output_);
61 pass.
push_constant(
"probe_coord_packed",
reinterpret_cast<int4 *
>(&probe_sampling_coord_));
62 pass.
push_constant(
"write_coord_packed",
reinterpret_cast<int4 *
>(&probe_write_coord_));
63 pass.
push_constant(
"read_coord_packed",
reinterpret_cast<int4 *
>(&probe_read_coord_));
66 pass.
dispatch(&dispatch_probe_convolve_);
72 pass.
push_constant(
"probe_remap_dispatch_size", &dispatch_probe_pack_);
73 pass.
bind_ssbo(
"in_sh", &tmp_spherical_harmonics_);
74 pass.
bind_ssbo(
"out_sh", &spherical_harmonics_);
82 pass.
push_constant(
"probe_remap_dispatch_size", &dispatch_probe_pack_);
84 pass.
bind_ssbo(
"sunlight_buf", &instance_.world.sunlight);
93 pass.
push_constant(
"lightprobe_sphere_count", &lightprobe_sphere_count_);
94 pass.
bind_ssbo(
"lightprobe_sphere_buf", &data_buf_);
95 instance_.volume_probes.bind_resources(pass);
96 instance_.sampling.bind_resources(pass);
98 pass.
dispatch(&dispatch_probe_select_);
103bool SphereProbeModule::ensure_atlas()
132 const bool atlas_resized = ensure_atlas();
134 instance_.light_probes.world_sphere_.do_render =
true;
136 const bool world_updated = instance_.light_probes.world_sphere_.do_render;
138 update_probes_next_sample_ =
false;
139 for (
SphereProbe &probe : instance_.light_probes.sphere_map_.values()) {
140 if (atlas_resized || world_updated) {
142 probe.do_render =
true;
144 if (probe.do_render) {
148 update_probes_next_sample_ =
true;
152 if (instance_.is_viewport()) {
158 if (instance_.do_lightprobe_sphere_sync()) {
159 instance_.sampling.reset();
162 if (update_probes_next_sample_ && (instance_.do_lightprobe_sphere_sync() ==
false)) {
168void SphereProbeModule::ensure_cubemap_render_target(
int resolution)
171 cubemap_tx_.
ensure_cube(gpu::TextureFormat::SFLOAT_16_16_16_16, resolution, usage);
175SphereProbeModule::UpdateInfo SphereProbeModule::update_info_from_probe(SphereProbe &probe)
177 SphereProbeModule::UpdateInfo info = {};
178 info.atlas_coord = probe.atlas_coord;
179 info.cube_target_extent = probe.atlas_coord.area_extent() / 2;
180 info.clipping_distances = probe.clipping_distances;
181 info.probe_pos = probe.location;
182 info.do_render = probe.do_render;
184 probe.do_render =
false;
185 probe.use_for_render =
true;
187 ensure_cubemap_render_target(info.cube_target_extent);
191std::optional<SphereProbeModule::UpdateInfo> SphereProbeModule::world_update_info_pop()
193 SphereProbe &world_probe = instance_.light_probes.world_sphere_;
194 if (world_probe.do_render) {
195 return update_info_from_probe(world_probe);
200std::optional<SphereProbeModule::UpdateInfo> SphereProbeModule::probe_update_info_pop()
202 if (!instance_.do_lightprobe_sphere_sync()) {
207 for (SphereProbe &probe : instance_.light_probes.sphere_map_.values()) {
208 if (!probe.do_render) {
211 return update_info_from_probe(probe);
218 bool extract_spherical_harmonics)
221 probe_sampling_coord_ = atlas_coord.as_sampling_coord();
222 probe_write_coord_ = atlas_coord.as_write_coord(0);
223 int resolution = probe_write_coord_.extent;
224 dispatch_probe_pack_ =
int3(
226 extract_sh_ = extract_spherical_harmonics;
227 instance_.manager->submit(remap_ps_);
232 convolve_input_ = probes_tx_.mip_view(
i);
233 convolve_output_ = probes_tx_.mip_view(
i + 1);
234 probe_read_coord_ = atlas_coord.as_write_coord(
i);
235 probe_write_coord_ = atlas_coord.as_write_coord(
i + 1);
236 int out_mip_res = probe_write_coord_.extent;
237 dispatch_probe_convolve_ =
int3(
239 instance_.manager->submit(convolve_ps_);
242 if (extract_spherical_harmonics) {
243 instance_.manager->submit(sum_sh_ps_);
244 instance_.manager->submit(sum_sun_ps_);
246 instance_.volume_probes.update_world_irradiance();
256 for (
auto &probe : instance_.light_probes.sphere_map_.values()) {
261 if (!probe.use_for_render) {
265 probe_active.
append(&probe);
271 if (a->volume != b->volume) {
273 return a->volume < b->volume;
295 for (
auto &probe : probe_active) {
296 data_buf_[probe_id++] = *probe;
299 data_buf_[probe_id++] = instance_.light_probes.world_sphere_;
302 data_buf_[probe_id].atlas_coord.layer = -1;
304 data_buf_.push_update();
306 lightprobe_sphere_count_ = probe_id;
307 dispatch_probe_select_.x =
divide_ceil_u(lightprobe_sphere_count_,
309 instance_.manager->submit(select_ps_);
311 sync_display(probe_active);
316 do_display_draw_ =
false;
317 if (!instance_.draw_overlays) {
321 int display_index = 0;
323 if (probe_active[
i]->viewport_display) {
324 SphereProbeDisplayData &sph_data = display_data_buf_.get_or_resize(display_index++);
325 sph_data.probe_index =
i;
326 sph_data.display_size = probe_active[
i]->viewport_display_size;
330 if (display_index == 0) {
333 do_display_draw_ =
true;
334 display_data_buf_.resize(display_index);
335 display_data_buf_.push_update();
340 if (!do_display_draw_) {
344 viewport_display_ps_.init();
348 viewport_display_ps_.framebuffer_set(&view_fb);
350 viewport_display_ps_.bind_resources(*
this);
351 viewport_display_ps_.bind_ssbo(
"display_data_buf", display_data_buf_);
352 viewport_display_ps_.draw_procedural(
GPU_PRIM_TRIS, 1, display_data_buf_.size() * 6);
354 instance_.manager->submit(viewport_display_ps_,
view);
MINLINE uint divide_ceil_u(uint a, uint b)
bool DEG_id_type_any_exists(const Depsgraph *depsgraph, short id_type)
@ GPU_BARRIER_SHADER_STORAGE
@ GPU_BARRIER_TEXTURE_FETCH
void GPU_memory_barrier(GPUBarrier barrier)
void GPU_texture_clear(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *data)
void GPU_texture_mipmap_mode(blender::gpu::Texture *texture, bool use_mipmap, bool use_filter)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_ATTACHMENT
BMesh const char void * data
IndexRange index_range() const
void append(const T &value)
bool ensure_2d_array(blender::gpu::TextureFormat format, int2 extent, int layers, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
bool ensure_mip_views(bool cube_as_array=false)
bool ensure_cube(blender::gpu::TextureFormat format, int extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, float *data=nullptr, int mip_len=1)
gpu::Texture * mip_view(int miplvl)
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 specialize_constant(gpu::Shader *shader, const char *name, const float &data)
void bind_image(const char *name, gpu::Texture *image)
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)
LightProbeModule light_probes
void set_view(View &view)
int probe_render_extent() const
void viewport_draw(View &view, gpu::FrameBuffer *view_fb)
void DRW_viewport_request_redraw()
@ DRW_STATE_CLIP_CONTROL_UNIT_RANGE
#define SPHERE_PROBE_REMAP_GROUP_SIZE
#define SPHERE_PROBE_ATLAS_RES
#define SPHERE_PROBE_SELECT_GROUP_SIZE
#define SPHERE_PROBE_MIPMAP_LEVELS
#define SPHERE_PROBE_GROUP_SIZE
detail::Pass< command::DrawCommandBuf > PassSimple
@ SPHERE_PROBE_IRRADIANCE
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
VecBase< int32_t, 4 > int4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
SphereProbeUvArea atlas_coord