EEVEE-Next: Add compute shader to downsample sphere probe
This has no functional change except that it might speed up probe updates since only updated pixels are processed. Ref #118256
This commit is contained in:
@@ -564,6 +564,7 @@ set(GLSL_SRC
|
||||
engines/eevee_next/shaders/eevee_ray_trace_screen_comp.glsl
|
||||
engines/eevee_next/shaders/eevee_ray_trace_screen_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_ray_types_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_reflection_probe_convolve_comp.glsl
|
||||
engines/eevee_next/shaders/eevee_reflection_probe_eval_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_reflection_probe_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_reflection_probe_remap_comp.glsl
|
||||
|
||||
@@ -97,7 +97,7 @@ struct SphereProbeAtlasCoord {
|
||||
{
|
||||
SphereProbePixelArea coord;
|
||||
coord.extent = atlas_extent >> (subdivision_lvl + mip_lvl);
|
||||
coord.offset = (area_location() * coord.extent) >> mip_lvl;
|
||||
coord.offset = area_location() * coord.extent;
|
||||
coord.layer = atlas_layer;
|
||||
return coord;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,17 @@ void SphereProbeModule::begin_sync()
|
||||
pass.push_constant("probe_brightness_clamp", probe_brightness_clamp);
|
||||
pass.dispatch(&dispatch_probe_pack_);
|
||||
}
|
||||
{
|
||||
PassSimple &pass = convolve_ps_;
|
||||
pass.init();
|
||||
pass.shader_set(instance_.shaders.static_shader_get(SPHERE_PROBE_CONVOLVE));
|
||||
pass.bind_image("in_atlas_mip_img", &convolve_input_);
|
||||
pass.bind_image("out_atlas_mip_img", &convolve_output_);
|
||||
pass.push_constant("write_coord_packed", reinterpret_cast<int4 *>(&probe_write_coord_));
|
||||
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
pass.dispatch(&dispatch_probe_convolve_);
|
||||
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
}
|
||||
{
|
||||
PassSimple &pass = update_irradiance_ps_;
|
||||
pass.init();
|
||||
@@ -85,6 +96,7 @@ bool SphereProbeModule::ensure_atlas()
|
||||
nullptr,
|
||||
SPHERE_PROBE_MIPMAP_LEVELS))
|
||||
{
|
||||
probes_tx_.ensure_mip_views();
|
||||
/* TODO(fclem): Clearing means that we need to render all probes again.
|
||||
* If existing data exists, copy it using `CopyImageSubData`. */
|
||||
probes_tx_.clear(float4(0.0f));
|
||||
@@ -187,8 +199,19 @@ void SphereProbeModule::remap_to_octahedral_projection(const SphereProbeAtlasCoo
|
||||
probe_write_coord_ = atlas_coord.as_write_coord(max_resolution_, 0);
|
||||
probe_mip_level_ = atlas_coord.subdivision_lvl;
|
||||
dispatch_probe_pack_ = int3(int2(ceil_division(resolution, SPHERE_PROBE_GROUP_SIZE)), 1);
|
||||
|
||||
instance_.manager->submit(remap_ps_);
|
||||
|
||||
/* Populate the mip levels */
|
||||
for (auto i : IndexRange(SPHERE_PROBE_MIPMAP_LEVELS - 1)) {
|
||||
convolve_input_ = probes_tx_.mip_view(i);
|
||||
convolve_output_ = probes_tx_.mip_view(i + 1);
|
||||
probe_write_coord_ = atlas_coord.as_write_coord(max_resolution_, i + 1);
|
||||
int out_mip_res = resolution >> (i + 1);
|
||||
dispatch_probe_convolve_ = int3(int2(ceil_division(out_mip_res, SPHERE_PROBE_GROUP_SIZE)), 1);
|
||||
instance_.manager->submit(convolve_ps_);
|
||||
}
|
||||
/* Sync with atlas usage for shading. */
|
||||
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
|
||||
}
|
||||
|
||||
void SphereProbeModule::update_world_irradiance()
|
||||
@@ -198,11 +221,6 @@ void SphereProbeModule::update_world_irradiance()
|
||||
instance_.volume_probes.do_update_world_ = true;
|
||||
}
|
||||
|
||||
void SphereProbeModule::update_probes_texture_mipmaps()
|
||||
{
|
||||
GPU_texture_update_mipmap_chain(probes_tx_);
|
||||
}
|
||||
|
||||
void SphereProbeModule::set_view(View & /*view*/)
|
||||
{
|
||||
Vector<SphereProbe *> probe_active;
|
||||
|
||||
@@ -53,9 +53,17 @@ class SphereProbeModule {
|
||||
PassSimple remap_ps_ = {"Probe.CubemapToOctahedral"};
|
||||
/** Extract irradiance information from the world. */
|
||||
PassSimple update_irradiance_ps_ = {"Probe.UpdateIrradiance"};
|
||||
/** Copy volume probe irradiance for the center of sphere probes. */
|
||||
PassSimple select_ps_ = {"Probe.Select"};
|
||||
/** Convolve the octahedral map to fill the Mip-map levels. */
|
||||
PassSimple convolve_ps_ = {"Probe.Convolve"};
|
||||
/** Input mip level for the convolution. */
|
||||
GPUTexture *convolve_input_ = nullptr;
|
||||
/** Output mip level for the convolution. */
|
||||
GPUTexture *convolve_output_ = nullptr;
|
||||
|
||||
int3 dispatch_probe_pack_ = int3(1);
|
||||
int3 dispatch_probe_convolve_ = int3(1);
|
||||
int3 dispatch_probe_select_ = int3(1);
|
||||
|
||||
/**
|
||||
@@ -167,7 +175,6 @@ class SphereProbeModule {
|
||||
* Internal processing passes.
|
||||
*/
|
||||
void remap_to_octahedral_projection(const SphereProbeAtlasCoord &atlas_coord);
|
||||
void update_probes_texture_mipmaps();
|
||||
void update_world_irradiance();
|
||||
|
||||
void sync_display(Vector<SphereProbe *> &probe_active);
|
||||
|
||||
@@ -214,6 +214,8 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_
|
||||
return "eevee_lightprobe_irradiance_ray";
|
||||
case LIGHTPROBE_IRRADIANCE_LOAD:
|
||||
return "eevee_lightprobe_irradiance_load";
|
||||
case SPHERE_PROBE_CONVOLVE:
|
||||
return "eevee_reflection_probe_convolve";
|
||||
case SPHERE_PROBE_REMAP:
|
||||
return "eevee_reflection_probe_remap";
|
||||
case SPHERE_PROBE_UPDATE_IRRADIANCE:
|
||||
|
||||
@@ -104,9 +104,10 @@ enum eShaderType {
|
||||
RAY_TRACE_PLANAR,
|
||||
RAY_TRACE_SCREEN,
|
||||
|
||||
SPHERE_PROBE_CONVOLVE,
|
||||
SPHERE_PROBE_REMAP,
|
||||
SPHERE_PROBE_UPDATE_IRRADIANCE,
|
||||
SPHERE_PROBE_SELECT,
|
||||
SPHERE_PROBE_UPDATE_IRRADIANCE,
|
||||
|
||||
SHADOW_CLIPMAP_CLEAR,
|
||||
SHADOW_DEBUG,
|
||||
|
||||
@@ -263,7 +263,6 @@ void CaptureView::render_world()
|
||||
}
|
||||
|
||||
inst_.sphere_probes.remap_to_octahedral_projection(update_info->atlas_coord);
|
||||
inst_.sphere_probes.update_probes_texture_mipmaps();
|
||||
}
|
||||
|
||||
if (update_info->do_world_irradiance_update) {
|
||||
@@ -277,10 +276,8 @@ void CaptureView::render_probes()
|
||||
{
|
||||
Framebuffer prepass_fb;
|
||||
View view = {"Capture.View"};
|
||||
bool do_update_mipmap_chain = false;
|
||||
while (const auto update_info = inst_.sphere_probes.probe_update_info_pop()) {
|
||||
GPU_debug_group_begin("Probe.Capture");
|
||||
do_update_mipmap_chain = true;
|
||||
|
||||
if (inst_.pipelines.data.is_probe_reflection != true) {
|
||||
inst_.pipelines.data.is_probe_reflection = true;
|
||||
@@ -334,11 +331,6 @@ void CaptureView::render_probes()
|
||||
inst_.pipelines.data.is_probe_reflection = false;
|
||||
inst_.uniform_data.push_update();
|
||||
}
|
||||
|
||||
if (do_update_mipmap_chain) {
|
||||
/* TODO: only update the regions that have been updated. */
|
||||
inst_.sphere_probes.update_probes_texture_mipmaps();
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/* Shader to convert cube-map to octahedral projection. */
|
||||
|
||||
#pragma BLENDER_REQUIRE(eevee_octahedron_lib.glsl)
|
||||
|
||||
SphereProbePixelArea reinterpret_as_write_coord(ivec4 packed_coord)
|
||||
{
|
||||
SphereProbePixelArea unpacked;
|
||||
unpacked.offset = packed_coord.xy;
|
||||
unpacked.extent = packed_coord.z;
|
||||
unpacked.layer = packed_coord.w;
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
SphereProbePixelArea write_coord = reinterpret_as_write_coord(write_coord_packed);
|
||||
|
||||
/* Texel in probe. */
|
||||
ivec2 local_texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
/* Exit when pixel being written doesn't fit in the area reserved for the probe. */
|
||||
if (any(greaterThanEqual(local_texel, ivec2(write_coord.extent)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
ivec2 texel_out = write_coord.offset + local_texel;
|
||||
vec4 color = vec4(0.0);
|
||||
color += imageLoad(in_atlas_mip_img, ivec3(texel_out * 2 + ivec2(0, 0), write_coord.layer));
|
||||
color += imageLoad(in_atlas_mip_img, ivec3(texel_out * 2 + ivec2(1, 0), write_coord.layer));
|
||||
color += imageLoad(in_atlas_mip_img, ivec3(texel_out * 2 + ivec2(0, 1), write_coord.layer));
|
||||
color += imageLoad(in_atlas_mip_img, ivec3(texel_out * 2 + ivec2(1, 1), write_coord.layer));
|
||||
color *= 0.25;
|
||||
|
||||
imageStore(out_atlas_mip_img, ivec3(texel_out, write_coord.layer), color);
|
||||
}
|
||||
@@ -54,6 +54,15 @@ GPU_SHADER_CREATE_INFO(eevee_reflection_probe_select)
|
||||
.compute_source("eevee_reflection_probe_select_comp.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_reflection_probe_convolve)
|
||||
.local_group_size(SPHERE_PROBE_GROUP_SIZE, SPHERE_PROBE_GROUP_SIZE)
|
||||
.additional_info("eevee_shared")
|
||||
.push_constant(Type::IVEC4, "write_coord_packed")
|
||||
.image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D_ARRAY, "in_atlas_mip_img")
|
||||
.image(1, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_atlas_mip_img")
|
||||
.compute_source("eevee_reflection_probe_convolve_comp.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_INTERFACE_INFO(eevee_display_probe_reflection_iface, "")
|
||||
.smooth(Type::VEC2, "lP")
|
||||
.flat(Type::INT, "probe_index");
|
||||
|
||||
Reference in New Issue
Block a user