16 return instance_.scene->eevee.gi_cubemap_resolution / 2;
21 if (!instance_.is_viewport()) {
27 do_display_draw_ =
false;
32 update_probes_this_sample_ = update_probes_next_sample_;
34 LightProbeModule &light_probes = instance_.light_probes;
47 pass.
bind_ssbo(
"out_sh", &tmp_spherical_harmonics_);
48 pass.
bind_ssbo(
"out_sun", &tmp_sunlight_);
49 pass.
push_constant(
"probe_coord_packed",
reinterpret_cast<int4 *
>(&probe_sampling_coord_));
50 pass.
push_constant(
"write_coord_packed",
reinterpret_cast<int4 *
>(&probe_write_coord_));
53 pass.
dispatch(&dispatch_probe_pack_);
61 pass.
bind_image(
"out_atlas_mip_img", &convolve_output_);
62 pass.
push_constant(
"probe_coord_packed",
reinterpret_cast<int4 *
>(&probe_sampling_coord_));
63 pass.
push_constant(
"write_coord_packed",
reinterpret_cast<int4 *
>(&probe_write_coord_));
64 pass.
push_constant(
"read_coord_packed",
reinterpret_cast<int4 *
>(&probe_read_coord_));
67 pass.
dispatch(&dispatch_probe_convolve_);
73 pass.
push_constant(
"probe_remap_dispatch_size", &dispatch_probe_pack_);
74 pass.
bind_ssbo(
"in_sh", &tmp_spherical_harmonics_);
75 pass.
bind_ssbo(
"out_sh", &spherical_harmonics_);
83 pass.
push_constant(
"probe_remap_dispatch_size", &dispatch_probe_pack_);
85 pass.
bind_ssbo(
"sunlight_buf", &instance_.world.sunlight);
94 pass.
push_constant(
"lightprobe_sphere_count", &lightprobe_sphere_count_);
95 pass.
bind_ssbo(
"lightprobe_sphere_buf", &data_buf_);
96 instance_.volume_probes.bind_resources(pass);
97 instance_.sampling.bind_resources(pass);
99 pass.
dispatch(&dispatch_probe_select_);
104bool SphereProbeModule::ensure_atlas()
133 const bool atlas_resized = ensure_atlas();
135 instance_.light_probes.world_sphere_.do_render =
true;
137 const bool world_updated = instance_.light_probes.world_sphere_.do_render;
139 update_probes_next_sample_ =
false;
140 for (
SphereProbe &probe : instance_.light_probes.sphere_map_.values()) {
141 if (atlas_resized || world_updated) {
143 probe.do_render =
true;
145 if (probe.do_render) {
149 update_probes_next_sample_ =
true;
158 if (instance_.do_lightprobe_sphere_sync()) {
159 instance_.sampling.reset();
162 if (update_probes_next_sample_ && (instance_.do_lightprobe_sphere_sync() ==
false)) {
167void SphereProbeModule::ensure_cubemap_render_target(
int resolution)
174SphereProbeModule::UpdateInfo SphereProbeModule::update_info_from_probe(SphereProbe &probe)
176 SphereProbeModule::UpdateInfo info = {};
177 info.atlas_coord = probe.atlas_coord;
178 info.cube_target_extent = probe.atlas_coord.area_extent() / 2;
179 info.clipping_distances = probe.clipping_distances;
180 info.probe_pos = probe.location;
181 info.do_render = probe.do_render;
183 probe.do_render =
false;
184 probe.use_for_render =
true;
186 ensure_cubemap_render_target(info.cube_target_extent);
190std::optional<SphereProbeModule::UpdateInfo> SphereProbeModule::world_update_info_pop()
192 SphereProbe &world_probe = instance_.light_probes.world_sphere_;
193 if (world_probe.do_render) {
194 return update_info_from_probe(world_probe);
199std::optional<SphereProbeModule::UpdateInfo> SphereProbeModule::probe_update_info_pop()
201 if (!instance_.do_lightprobe_sphere_sync()) {
206 for (SphereProbe &probe : instance_.light_probes.sphere_map_.values()) {
207 if (!probe.do_render) {
210 return update_info_from_probe(probe);
217 bool extract_spherical_harmonics)
220 probe_sampling_coord_ = atlas_coord.as_sampling_coord();
221 probe_write_coord_ = atlas_coord.as_write_coord(0);
222 int resolution = probe_write_coord_.extent;
223 dispatch_probe_pack_ =
int3(
225 extract_sh_ = extract_spherical_harmonics;
226 instance_.manager->submit(remap_ps_);
231 convolve_input_ = probes_tx_.mip_view(i);
232 convolve_output_ = probes_tx_.mip_view(i + 1);
233 probe_read_coord_ = atlas_coord.as_write_coord(i);
234 probe_write_coord_ = atlas_coord.as_write_coord(i + 1);
235 int out_mip_res = probe_write_coord_.extent;
236 dispatch_probe_convolve_ =
int3(
238 instance_.manager->submit(convolve_ps_);
241 if (extract_spherical_harmonics) {
242 instance_.manager->submit(sum_sh_ps_);
243 instance_.manager->submit(sum_sun_ps_);
245 instance_.volume_probes.update_world_irradiance();
255 for (
auto &probe : instance_.light_probes.sphere_map_.values()) {
260 if (!probe.use_for_render) {
264 probe_active.
append(&probe);
270 if (a->volume != b->volume) {
272 return a->volume < b->volume;
294 for (
auto &probe : probe_active) {
295 data_buf_[probe_id++] = *probe;
298 data_buf_[probe_id++] = instance_.light_probes.world_sphere_;
301 data_buf_[probe_id].atlas_coord.layer = -1;
303 data_buf_.push_update();
305 lightprobe_sphere_count_ = probe_id;
306 dispatch_probe_select_.x =
divide_ceil_u(lightprobe_sphere_count_,
308 instance_.manager->submit(select_ps_);
310 sync_display(probe_active);
315 do_display_draw_ =
false;
320 int display_index = 0;
322 if (probe_active[i]->viewport_display) {
324 sph_data.probe_index = i;
325 sph_data.display_size = probe_active[i]->viewport_display_size;
329 if (display_index == 0) {
332 do_display_draw_ =
true;
333 display_data_buf_.resize(display_index);
334 display_data_buf_.push_update();
339 if (!do_display_draw_) {
343 viewport_display_ps_.init();
346 viewport_display_ps_.framebuffer_set(&view_fb);
348 viewport_display_ps_.bind_resources(*
this);
349 viewport_display_ps_.bind_ssbo(
"display_data_buf", display_data_buf_);
350 viewport_display_ps_.draw_procedural(
GPU_PRIM_TRIS, 1, display_data_buf_.size() * 6);
352 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)
void GPU_memory_barrier(eGPUBarrier barrier)
@ GPU_BARRIER_SHADER_STORAGE
@ GPU_BARRIER_TEXTURE_FETCH
void GPU_texture_clear(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_ATTACHMENT
void GPU_texture_mipmap_mode(GPUTexture *texture, bool use_mipmap, bool use_filter)
struct GPUShader GPUShader
IndexRange index_range() const
void append(const T &value)
bool ensure_mip_views(bool cube_as_array=false)
bool ensure_cube(eGPUTextureFormat format, int extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, float *data=nullptr, int mip_len=1)
bool ensure_2d_array(eGPUTextureFormat format, int2 extent, int layers, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
GPUTexture * mip_view(int miplvl)
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)
void specialize_constant(GPUShader *shader, const char *name, const float &data)
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)
LightProbeModule light_probes
void set_view(View &view)
void viewport_draw(View &view, GPUFrameBuffer *view_fb)
int probe_render_extent() const
local_group_size(16, 16) .push_constant(Type b
bool DRW_state_draw_support()
void DRW_viewport_request_redraw()
@ DRW_STATE_DEPTH_LESS_EQUAL
#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
local_group_size(SPHERE_PROBE_GROUP_SIZE, SPHERE_PROBE_GROUP_SIZE) .additional_info("eevee_shared") .push_constant(Type smooth(Type::VEC3, "P") .smooth(Type SphereProbeDisplayData
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