EEVEE-Next: Irradiance Volume: Add clamp options #110858
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ struct IrradianceGrid : public LightProbe, IrradianceGridData {
|
|||
float validity_threshold;
|
||||
float dilation_threshold;
|
||||
float dilation_radius;
|
||||
float intensity;
|
||||
};
|
||||
|
||||
struct ReflectionCube : public LightProbe {
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue