EEVEE-Next: Irradiance Volume: Add clamp options #110858

Merged
Clément Foucault merged 1 commits from fclem/blender:eevee-next-irradiance-intensity into main 2023-09-04 23:27:40 +02:00
12 changed files with 57 additions and 0 deletions

View File

@ -103,6 +103,10 @@ class DATA_PT_lightprobe_eevee_next(DataButtonsPanel, Panel):
col.separator()
col.prop(probe, "intensity")
col.separator()
col.operator("object.lightprobe_cache_bake").subset = "ACTIVE"
col.operator("object.lightprobe_cache_free").subset = "ACTIVE"
@ -113,6 +117,11 @@ class DATA_PT_lightprobe_eevee_next(DataButtonsPanel, Panel):
col.separator()
col.prop(probe, "grid_clamp_direct")
col.prop(probe, "grid_clamp_indirect")
col.separator()
col.prop(probe, "grid_normal_bias")
col.prop(probe, "grid_view_bias")
col.prop(probe, "grid_irradiance_smoothing")

View File

@ -343,6 +343,7 @@ void IrradianceCache::set_view(View & /*view*/)
grid_upload_ps_.push_constant("grid_index", grid->grid_index);
grid_upload_ps_.push_constant("grid_start_index", grid_start_index);
grid_upload_ps_.push_constant("grid_local_to_world", grid->object_to_world);
grid_upload_ps_.push_constant("grid_intensity_factor", grid->intensity);
grid_upload_ps_.bind_ubo("grids_infos_buf", &grids_infos_buf_);
grid_upload_ps_.bind_ssbo("bricks_infos_buf", &bricks_infos_buf_);
grid_upload_ps_.bind_texture("irradiance_a_tx", &irradiance_a_tx);
@ -786,6 +787,12 @@ void IrradianceBake::surfels_create(const Object &probe_object)
float min_distance_between_grid_samples = min_fff(UNPACK3(scale));
capture_info_buf_.min_distance_to_surface *= min_distance_between_grid_samples;
capture_info_buf_.max_virtual_offset *= min_distance_between_grid_samples;
capture_info_buf_.clamp_direct = (lightprobe->grid_clamp_direct > 0.0) ?
lightprobe->grid_clamp_direct :
1e20f;
capture_info_buf_.clamp_indirect = (lightprobe->grid_clamp_indirect > 0.0) ?
lightprobe->grid_clamp_indirect :
1e20f;
eGPUTextureUsage texture_usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE |
GPU_TEXTURE_USAGE_HOST_READ;

View File

@ -47,6 +47,7 @@ void LightProbeModule::sync_grid(const Object *ob, ObjectHandle &handle)
grid.validity_threshold = lightprobe->grid_validity_threshold;
grid.dilation_threshold = lightprobe->grid_dilation_threshold;
grid.dilation_radius = lightprobe->grid_dilation_radius;
grid.intensity = lightprobe->intensity;
/* Force reupload. */
inst_.irradiance_cache.bricks_free(grid.bricks);
}

View File

@ -50,6 +50,7 @@ struct IrradianceGrid : public LightProbe, IrradianceGridData {
float validity_threshold;
float dilation_threshold;
float dilation_radius;
float intensity;
};
struct ReflectionCube : public LightProbe {

View File

@ -993,6 +993,11 @@ struct CaptureInfoData {
int scene_bound_x_max;
int scene_bound_y_max;
int scene_bound_z_max;
/* Max intensity a ray can have. */
float clamp_direct;
float clamp_indirect;
float _pad1;
float _pad2;
/** Minimum distance between a grid sample and a surface. Used to compute virtual offset. */
float min_distance_to_surface;
/** Maximum world scale offset an irradiance grid sample can be baked with. */

View File

@ -110,6 +110,8 @@ void main()
SphericalHarmonicL1 sh_distant = lightprobe_irradiance_sample(P);
/* Mask distant lighting by local visibility. */
sh_distant = spherical_harmonics_triple_product(sh_visibility, sh_distant);
/* Apply intensity scaling. */
sh_local = spherical_harmonics_mul(sh_local, grid_intensity_factor);
/* Add local lighting to distant lighting. */
sh_local = spherical_harmonics_add(sh_local, sh_distant);

View File

@ -34,6 +34,11 @@ void irradiance_capture_surfel(Surfel surfel, vec3 P, inout SphericalHarmonicL1
vec4 irradiance_vis = vec4(0.0);
irradiance_vis += facing ? surfel.radiance_direct.front : surfel.radiance_direct.back;
/* Clamped brightness. */
float luma = max(1e-8, max_v3(irradiance_vis.rgb));
irradiance_vis.rgb *= 1.0 - max(0.0, luma - capture_info_buf.clamp_direct) / luma;
/* NOTE: The indirect radiance is already normalized and this is wanted, because we are not
* integrating the same signal and we would have the SH lagging behind the surfel integration
* otherwise. */
@ -61,6 +66,10 @@ void irradiance_capture_world(vec3 L, inout SphericalHarmonicL1 sh)
if (capture_info_buf.capture_world_direct) {
radiance = reflection_probes_world_sample(L, 0.0).rgb;
/* Clamped brightness. */
float luma = max(1e-8, max_v3(radiance));
radiance *= 1.0 - max(0.0, luma - capture_info_buf.clamp_direct) / luma;
}
if (capture_info_buf.capture_visibility_direct) {

View File

@ -21,6 +21,10 @@ float avg_albedo(vec3 albedo)
void radiance_transfer(inout Surfel surfel, vec3 in_radiance, float in_visibility, vec3 L)
{
/* Clamped brightness. */
float luma = max(1e-8, max_v3(in_radiance));
in_radiance *= 1.0 - max(0.0, luma - capture_info_buf.clamp_indirect) / luma;
float NL = dot(surfel.normal, L);
/* Lambertian BSDF. Albedo applied later depending on which side of the surfel was hit. */
const float bsdf = M_1_PI;

View File

@ -176,6 +176,7 @@ GPU_SHADER_CREATE_INFO(eevee_lightprobe_irradiance_load)
.push_constant(Type::FLOAT, "validity_threshold")
.push_constant(Type::FLOAT, "dilation_threshold")
.push_constant(Type::FLOAT, "dilation_radius")
.push_constant(Type::FLOAT, "grid_intensity_factor")
.uniform_buf(0, "IrradianceGridData", "grids_infos_buf[IRRADIANCE_GRID_MAX]")
.storage_buf(0, Qualifier::READ, "uint", "bricks_infos_buf[]")
.sampler(0, ImageType::FLOAT_3D, "irradiance_a_tx")

View File

@ -29,6 +29,8 @@
.grid_validity_threshold = 0.40f, \
.grid_dilation_threshold = 0.5f, \
.grid_dilation_radius = 1.0f, \
.grid_clamp_direct = 0.0f, \
.grid_clamp_indirect = 10.0f, \
.surfel_density = 1.0f, \
.distinf = 2.5f, \
.distpar = 2.5f, \

View File

@ -72,6 +72,9 @@ typedef struct LightProbe {
float grid_dilation_threshold;
float grid_dilation_radius;
char _pad1[4];
/** Light intensity clamp. */
float grid_clamp_direct;
float grid_clamp_indirect;
/** Surface element density for scene surface cache. In surfel per unit distance. */
float surfel_density;

View File

@ -263,6 +263,19 @@ static void rna_def_lightprobe(BlenderRNA *brna)
prop, "Capture Emission", "Bake emissive surfaces for more accurate lighting");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, nullptr);
prop = RNA_def_property(srna, "grid_clamp_direct", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(
prop, "Clamp Direct", "Clamp the direct lighting intensity to reduce noise (0 to disable)");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
prop = RNA_def_property(srna, "grid_clamp_indirect", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(prop,
"Clamp Indirect",
"Clamp the indirect lighting intensity to reduce noise (0 to disable)");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
prop = RNA_def_property(srna, "visibility_buffer_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, nullptr, "vis_bias");
RNA_def_property_range(prop, 0.001f, 9999.0f);