WIP: eevee-next-world-irradiance #108304

Closed
Jeroen Bakker wants to merge 79 commits from Jeroen-Bakker:eevee-next-world-irradiance into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
12 changed files with 87 additions and 29 deletions
Showing only changes of commit 73f96fe216 - Show all commits

View File

@ -596,6 +596,7 @@ class RENDER_PT_eevee_next_indirect_lighting(RenderButtonsPanel, Panel):
col.label(text=cache_info)
col.prop(props, "gi_auto_bake")
col.prop(props, "gi_diffuse_bounces")
col.prop(props, "gi_irradiance_samples")

View File

@ -499,6 +499,7 @@ set(GLSL_SRC
engines/eevee_next/shaders/eevee_surf_lib.glsl
engines/eevee_next/shaders/eevee_surf_shadow_frag.glsl
engines/eevee_next/shaders/eevee_surf_world_frag.glsl
engines/eevee_next/shaders/eevee_surfel_bounce_comp.glsl
engines/eevee_next/shaders/eevee_surfel_light_comp.glsl
engines/eevee_next/shaders/eevee_surfel_list_build_comp.glsl
engines/eevee_next/shaders/eevee_surfel_list_sort_comp.glsl

View File

@ -535,19 +535,20 @@ void Instance::light_bake_irradiance(LightCache *&r_light_cache,
return;
}
/* TODO(fclem): Multiple bounce. We need to use the previous bounce result. */
for (int bounce = 0; bounce < 1; bounce++) {
for (auto i : light_probes.grids.index_range()) {
custom_pipeline_wrapper([&]() {
/* TODO: lightprobe visibility group option. */
manager->begin_sync();
render_sync();
manager->end_sync();
irradiance_cache.bake.surfels_create(light_probes.grids[i]);
irradiance_cache.bake.surfels_lights_eval();
});
for (auto i : light_probes.grids.index_range()) {
custom_pipeline_wrapper([&]() {
/* TODO: lightprobe visibility group option. */
manager->begin_sync();
render_sync();
manager->end_sync();
irradiance_cache.bake.surfels_create(light_probes.grids[i]);
irradiance_cache.bake.surfels_lights_eval();
});
sampling.reset();
int bounce_len = scene->eevee.gi_diffuse_bounces;
/* Start at bounce 1 as 0 bounce is no indirect lighting. */
for (int bounce = 1; bounce <= bounce_len; bounce++) {
sampling.init(scene);
while (!sampling.finished()) {
context_wrapper([&]() {
/* Batch ray cast by pack of 16 to avoid too much overhead of
@ -556,11 +557,19 @@ void Instance::light_bake_irradiance(LightCache *&r_light_cache,
sampling.step();
irradiance_cache.bake.propagate_light_sample();
}
if (sampling.finished()) {
irradiance_cache.bake.accumulate_bounce();
}
irradiance_cache.bake.read_result(r_light_cache->grids[i]);
});
// do_update = true;
}
}
if (bounce_len == 0) {
/* Still read result for debugging surfel direct lighting. */
context_wrapper([&]() { irradiance_cache.bake.read_result(r_light_cache->grids[i]); });
}
}
r_light_cache->flag &= ~LIGHTCACHE_BAKING;

View File

@ -124,6 +124,7 @@ void IrradianceBake::sync()
PassSimple::Sub &sub = pass.sub("ListSort");
sub.shader_set(inst_.shaders.static_shader_get(SURFEL_LIST_SORT));
sub.bind_ssbo(SURFEL_BUF_SLOT, &surfels_buf_);
sub.bind_ssbo(CAPTURE_BUF_SLOT, &capture_info_buf_);
sub.bind_ssbo("list_start_buf", &list_start_buf_);
sub.bind_ssbo("list_info_buf", &list_info_buf_);
sub.barrier(GPU_BARRIER_SHADER_STORAGE);
@ -143,6 +144,15 @@ void IrradianceBake::sync()
pass.init();
/* TODO */
}
{
PassSimple &pass = surfel_light_bounce_ps_;
pass.init();
pass.shader_set(inst_.shaders.static_shader_get(SURFEL_BOUNCE));
pass.bind_ssbo(SURFEL_BUF_SLOT, &surfels_buf_);
pass.bind_ssbo(CAPTURE_BUF_SLOT, &capture_info_buf_);
pass.barrier(GPU_BARRIER_SHADER_STORAGE);
pass.dispatch(&dispatch_per_surfel_);
}
}
void IrradianceBake::surfels_create(const IrradianceGrid &grid)
@ -304,6 +314,11 @@ void IrradianceBake::propagate_light_sample()
inst_.manager->submit(surfel_light_propagate_ps_, ray_view);
}
void IrradianceBake::accumulate_bounce()
{
inst_.manager->submit(surfel_light_bounce_ps_);
}
void IrradianceBake::read_result(LightCacheIrradianceGrid &light_cache_grid)
{
switch (inst_.debug_mode) {

View File

@ -39,6 +39,8 @@ class IrradianceBake {
PassSimple surfel_light_eval_ps_ = {"LightEval"};
/** Propagate light from surfel to surfel. */
PassSimple surfel_light_propagate_ps_ = {"LightPropagate"};
/** Start of a light bounce. Accumulate light from previous propagation. */
PassSimple surfel_light_bounce_ps_ = {"LightBounce"};
/** Capture surfel lighting to irradiance samples. */
PassSimple irradiance_capture_ps_ = {"IrradianceCapture"};
@ -85,6 +87,8 @@ class IrradianceBake {
void surfels_lights_eval();
/** Propagate light from surfel to surfel in a random direction over the sphere. */
void propagate_light_sample();
/** Accumulate light inside `surfel.radiance_bounce` to `surfel.radiance`. */
void accumulate_bounce();
/** Read grid final irradiance back to CPU into \a light_cache_grid . */
void read_result(LightCacheIrradianceGrid &light_cache_grid);

View File

@ -26,6 +26,7 @@ void Sampling::init(const Scene *scene)
{
if (inst_.is_baking()) {
sample_count_ = max_ii(1, scene->eevee.gi_irradiance_samples);
sample_ = 0;
}
else {
sample_count_ = inst_.is_viewport() ? scene->eevee.taa_samples :

View File

@ -172,6 +172,8 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_
return "eevee_shadow_tag_usage_opaque";
case SHADOW_TILEMAP_TAG_USAGE_TRANSPARENT:
return "eevee_shadow_tag_usage_transparent";
case SURFEL_BOUNCE:
return "eevee_surfel_bounce";
case SURFEL_LIGHT:
return "eevee_surfel_light";
case SURFEL_LIST_BUILD:

View File

@ -80,6 +80,7 @@ enum eShaderType {
SHADOW_TILEMAP_TAG_USAGE_OPAQUE,
SHADOW_TILEMAP_TAG_USAGE_TRANSPARENT,
SURFEL_BOUNCE,
SURFEL_LIGHT,
SURFEL_LIST_BUILD,
SURFEL_LIST_SORT,

View File

@ -3,8 +3,6 @@ void main()
{
Surfel surfel = surfels_buf[surfel_index];
vec4 radiance_bounce = gl_FrontFacing ? surfel.radiance_bounce_front :
surfel.radiance_bounce_back;
vec3 radiance = gl_FrontFacing ? surfel.radiance_front : surfel.radiance_back;
switch (eDebugMode(debug_mode)) {
@ -13,9 +11,7 @@ void main()
out_color = vec4(pow(surfel.normal * 0.5 + 0.5, vec3(2.2)), 0.0);
break;
case DEBUG_IRRADIANCE_CACHE_SURFELS_IRRADIANCE:
out_color = (radiance_bounce.w > 0.0) ?
vec4(radiance + radiance_bounce.rgb / radiance_bounce.w, 0.0) :
vec4(radiance, 0.0);
out_color = vec4(radiance, 0.0);
break;
}

View File

@ -0,0 +1,24 @@
/**
* Accumulate light from a bounce of indirect light into each surfel radiance.
* This feeds back the light for the next bounce.
*/
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
void main()
{
int surfel_index = int(gl_GlobalInvocationID);
if (surfel_index >= capture_info_buf.surfel_len) {
return;
}
vec4 radiance_bounce_front = surfel_buf[surfel_index].radiance_bounce_front;
vec4 radiance_bounce_back = surfel_buf[surfel_index].radiance_bounce_back;
surfel_buf[surfel_index].radiance_front += radiance_bounce_front.rgb *
safe_rcp(radiance_bounce_front.w);
surfel_buf[surfel_index].radiance_back += radiance_bounce_back.rgb *
safe_rcp(radiance_bounce_back.w);
surfel_buf[surfel_index].radiance_bounce_front = vec4(0.0);
surfel_buf[surfel_index].radiance_bounce_back = vec4(0.0);
}

View File

@ -20,13 +20,13 @@
*/
void radiance_transfer(Surfel surfel_a, inout Surfel surfel_b)
{
bool facing = dot(surfel_a.normal, surfel_b.normal) < 0.0;
vec3 L = normalize(surfel_a.position - surfel_b.position);
vec3 N = surfel_b.normal;
float NL = dot(N, L);
float pdf = abs(NL);
bool facing = dot(-L, surfel_a.normal) > 0.0;
vec3 irradiance = facing ? surfel_a.radiance_front : surfel_a.radiance_back;
irradiance *= M_1_PI;
if (NL > 0.0) {
surfel_b.radiance_bounce_front += vec4(surfel_b.albedo_front * irradiance * pdf, pdf);

View File

@ -18,41 +18,45 @@ GPU_SHADER_CREATE_INFO(eevee_debug_surfels)
.push_constant(Type::INT, "debug_mode")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(eevee_surfel_common)
.storage_buf(SURFEL_BUF_SLOT, Qualifier::READ_WRITE, "Surfel", "surfel_buf[]")
.storage_buf(CAPTURE_BUF_SLOT, Qualifier::READ, "CaptureInfoData", "capture_info_buf");
GPU_SHADER_CREATE_INFO(eevee_surfel_light)
.local_group_size(SURFEL_GROUP_SIZE)
.additional_info("eevee_shared",
"draw_view",
"eevee_utility_texture",
"eevee_surfel_common",
"eevee_light_data",
"eevee_shadow_data")
.compute_source("eevee_surfel_light_comp.glsl")
.storage_buf(SURFEL_BUF_SLOT, Qualifier::READ_WRITE, "Surfel", "surfel_buf[]")
.storage_buf(CAPTURE_BUF_SLOT, Qualifier::READ, "CaptureInfoData", "capture_info_buf")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(eevee_surfel_bounce)
.local_group_size(SURFEL_GROUP_SIZE)
.additional_info("eevee_shared", "eevee_surfel_common")
.compute_source("eevee_surfel_bounce_comp.glsl")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(eevee_surfel_list_build)
.local_group_size(SURFEL_GROUP_SIZE)
.additional_info("eevee_shared", "draw_view")
.additional_info("eevee_shared", "eevee_surfel_common", "draw_view")
.storage_buf(0, Qualifier::READ_WRITE, "int", "list_start_buf[]")
.storage_buf(SURFEL_BUF_SLOT, Qualifier::READ_WRITE, "Surfel", "surfel_buf[]")
.storage_buf(CAPTURE_BUF_SLOT, Qualifier::READ, "CaptureInfoData", "capture_info_buf")
.storage_buf(6, Qualifier::READ_WRITE, "SurfelListInfoData", "list_info_buf")
.compute_source("eevee_surfel_list_build_comp.glsl")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(eevee_surfel_list_sort)
.local_group_size(SURFEL_LIST_GROUP_SIZE)
.additional_info("eevee_shared", "draw_view")
.additional_info("eevee_shared", "eevee_surfel_common", "draw_view")
.storage_buf(0, Qualifier::READ_WRITE, "int", "list_start_buf[]")
.storage_buf(SURFEL_BUF_SLOT, Qualifier::READ_WRITE, "Surfel", "surfel_buf[]")
.storage_buf(6, Qualifier::READ, "SurfelListInfoData", "list_info_buf")
.compute_source("eevee_surfel_list_sort_comp.glsl")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(eevee_surfel_ray)
.local_group_size(SURFEL_GROUP_SIZE)
.additional_info("eevee_shared", "draw_view")
.storage_buf(SURFEL_BUF_SLOT, Qualifier::READ_WRITE, "Surfel", "surfel_buf[]")
.storage_buf(CAPTURE_BUF_SLOT, Qualifier::READ, "CaptureInfoData", "capture_info_buf")
.additional_info("eevee_shared", "eevee_surfel_common", "draw_view")
.compute_source("eevee_surfel_ray_comp.glsl")
.do_static_compilation(true);