Eevee: Add Glossy Reflection clamping

This enables reducing the noise comming from very bright light sources
(like a sun) that can be found in distant HDRIs.

The lost energy may be replaced manually by a sunlight that compensate the
this loss.

This clamping only concerns Reflection Cubmaps and is done on all on all
of them.

Setting to 0.0 disables it (default).
This commit is contained in:
Clément Foucault 2018-11-15 19:41:15 +01:00
parent f8964809b8
commit 1b321048a7
7 changed files with 43 additions and 11 deletions

View File

@ -447,6 +447,7 @@ class RENDER_PT_eevee_indirect_lighting(RenderButtonsPanel, Panel):
col.prop(props, "gi_cubemap_resolution")
col.prop(props, "gi_visibility_resolution", text="Diffuse Occlusion")
col.prop(props, "gi_irradiance_smoothing")
col.prop(props, "gi_glossy_clamp")
class RENDER_PT_eevee_indirect_lighting_display(RenderButtonsPanel, Panel):

View File

@ -118,7 +118,6 @@ typedef struct EEVEE_LightBake {
int grid_sample_len; /* Total number of samples for the current grid. */
int grid_curr; /* Nth grid in the cache being rendered. */
int bounce_curr, bounce_len; /* The current light bounce being evaluated. */
float vis_range, vis_blur; /* Sample Visibility compression and bluring. */
float vis_res; /* Resolution of the Visibility shadowmap. */
GPUTexture *grid_prev; /* Result of previous light bounce. */
LightProbe **grid_prb; /* Pointer to the id.data of the probe object. */
@ -127,9 +126,6 @@ typedef struct EEVEE_LightBake {
EEVEE_LightProbe *cube; /* Current probe being rendered (UBO data). */
int ref_cube_res; /* Target cubemap at MIP 0. */
int cube_offset; /* Index of the current cube. */
float probemat[6][4][4]; /* ViewProjection matrix for each cube face. */
float texel_size, padding_size; /* Texel and padding size for the final octahedral map. */
float roughness; /* Roughness level of the current mipmap. */
LightProbe **cube_prb; /* Pointer to the id.data of the probe object. */
/* Dummy Textures */
@ -745,12 +741,21 @@ static void eevee_lightbake_render_world_sample(void *ved, void *user_data)
EEVEE_LightBake *lbake = (EEVEE_LightBake *)user_data;
Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
LightCache *lcache = scene_eval->eevee.light_cache;
float clamp = scene_eval->eevee.gi_glossy_clamp;
/* TODO do this once for the whole bake when we have independent DRWManagers. */
eevee_lightbake_cache_create(vedata, lbake);
sldata->common_data.ray_type = EEVEE_RAY_GLOSSY;
sldata->common_data.ray_depth = 1;
DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
EEVEE_lightbake_render_world(sldata, vedata, lbake->rt_fb);
EEVEE_lightbake_filter_glossy(sldata, vedata, lbake->rt_color, lbake->store_fb, 0, 1.0f, lcache->mips_len, clamp);
sldata->common_data.ray_type = EEVEE_RAY_DIFFUSE;
sldata->common_data.ray_depth = 1;
DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
EEVEE_lightbake_render_world(sldata, vedata, lbake->rt_fb);
EEVEE_lightbake_filter_glossy(sldata, vedata, lbake->rt_color, lbake->store_fb, 0, 1.0f, lcache->mips_len);
EEVEE_lightbake_filter_diffuse(sldata, vedata, lbake->rt_color, lbake->store_fb, 0, 1.0f);
/* Clear the cache to avoid white values in the grid. */
@ -919,6 +924,7 @@ static void eevee_lightbake_render_probe_sample(void *ved, void *user_data)
LightCache *lcache = scene_eval->eevee.light_cache;
EEVEE_LightProbe *eprobe = lbake->cube;
LightProbe *prb = *lbake->probe;
float clamp = scene_eval->eevee.gi_glossy_clamp;
/* TODO do this once for the whole bake when we have independent DRWManagers. */
eevee_lightbake_cache_create(vedata, lbake);
@ -932,7 +938,8 @@ static void eevee_lightbake_render_probe_sample(void *ved, void *user_data)
DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
EEVEE_lightbake_render_scene(sldata, vedata, lbake->rt_fb, eprobe->position, prb->clipsta, prb->clipend);
EEVEE_lightbake_filter_glossy(sldata, vedata, lbake->rt_color, lbake->store_fb, lbake->cube_offset, prb->intensity, lcache->mips_len);
EEVEE_lightbake_filter_glossy(sldata, vedata, lbake->rt_color, lbake->store_fb, lbake->cube_offset,prb->intensity,
lcache->mips_len, clamp);
lcache->cube_len += 1;
@ -1167,6 +1174,7 @@ void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float
void EEVEE_lightbake_update_world_quick(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, const Scene *scene)
{
LightCache *lcache = vedata->stl->g_data->light_cache;
float clamp = scene->eevee.gi_glossy_clamp;
EEVEE_LightBake lbake = {
.resource_only = true
@ -1181,7 +1189,7 @@ void EEVEE_lightbake_update_world_quick(EEVEE_ViewLayerData *sldata, EEVEE_Data
sldata->common_data.ray_depth = 1;
DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
EEVEE_lightbake_render_world(sldata, vedata, lbake.rt_fb);
EEVEE_lightbake_filter_glossy(sldata, vedata, lbake.rt_color, lbake.store_fb, 0, 1.0f, lcache->mips_len);
EEVEE_lightbake_filter_glossy(sldata, vedata, lbake.rt_color, lbake.store_fb, 0, 1.0f, lcache->mips_len, clamp);
sldata->common_data.ray_type = EEVEE_RAY_DIFFUSE;
sldata->common_data.ray_depth = 1;

View File

@ -376,6 +376,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
DRW_shgroup_uniform_float(grp, "texelSize", &pinfo->texel_size, 1);
DRW_shgroup_uniform_float(grp, "paddingSize", &pinfo->padding_size, 1);
DRW_shgroup_uniform_float(grp, "fireflyFactor", &pinfo->firefly_fac, 1);
DRW_shgroup_uniform_int(grp, "Layer", &pinfo->layer, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
@ -1102,7 +1103,7 @@ static void eevee_lightbake_render_scene_to_planars(
void EEVEE_lightbake_filter_glossy(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
struct GPUTexture *rt_color, struct GPUFrameBuffer *fb,
int probe_idx, float intensity, int maxlevel)
int probe_idx, float intensity, int maxlevel, float firefly_fac)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
@ -1151,6 +1152,7 @@ void EEVEE_lightbake_filter_glossy(
pinfo->samples_len_inv = 1.0f / pinfo->samples_len;
pinfo->lodfactor = bias + 0.5f * log((float)(target_size * target_size) * pinfo->samples_len_inv) / log(2);
pinfo->firefly_fac = (firefly_fac > 0.0) ? firefly_fac : 1e16;
GPU_framebuffer_ensure_config(&fb, {
GPU_ATTACHMENT_NONE,

View File

@ -480,6 +480,7 @@ typedef struct EEVEE_LightProbesInfo {
float near_clip;
float far_clip;
float roughness;
float firefly_fac;
float lodfactor;
float lod_rt_max, lod_cube_max, lod_planar_max;
float visibility_range;
@ -888,7 +889,7 @@ void EEVEE_lightbake_render_scene(
const float pos[3], float near_clip, float far_clip);
void EEVEE_lightbake_filter_glossy(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUTexture *rt_color, struct GPUFrameBuffer *fb,
int probe_idx, float intensity, int maxlevel);
int probe_idx, float intensity, int maxlevel, float firefly_fac);
void EEVEE_lightbake_filter_diffuse(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUTexture *rt_color, struct GPUFrameBuffer *fb,
int grid_offset, float intensity);

View File

@ -6,11 +6,17 @@ uniform float lodFactor;
uniform float lodMax;
uniform float paddingSize;
uniform float intensityFac;
uniform float fireflyFactor;
in vec3 worldPosition;
out vec4 FragColor;
float brightness(vec3 c)
{
return max(max(c.r, c.g), c.b);
}
vec3 octahedral_to_cubemap_proj(vec2 co)
{
co = co * 2.0 - 1.0;
@ -77,7 +83,13 @@ void main() {
/* http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html : Equation 13 */
float lod = clamp(lodFactor - 0.5 * log2(pdf * dist), 0.0, lodMax) ;
out_radiance += textureLod(probeHdr, L, lod).rgb * NL;
vec3 l_col = textureLod(probeHdr, L, lod).rgb;
/* Clamped brightness. */
float luma = max(1e-8, brightness(l_col));
l_col *= 1.0 - max(0.0, luma - fireflyFactor) / luma;
out_radiance += l_col * NL;
weight += NL;
}
}

View File

@ -1461,7 +1461,7 @@ typedef struct SceneEEVEE {
int gi_cubemap_resolution;
int gi_visibility_resolution;
float gi_irradiance_smoothing;
float pad;
float gi_glossy_clamp;
float gi_cubemap_draw_size;
float gi_irradiance_draw_size;

View File

@ -5687,6 +5687,14 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 5, 2);
RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_ui_text(prop, "Irradiance Smoothing", "Smoother irradiance interpolation but introduce light bleeding");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
prop = RNA_def_property(srna, "gi_glossy_clamp", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 0.0f);
RNA_def_property_ui_text(prop, "Clamp Glossy", "Clamp pixel intensity to reduce noise inside glossy reflections "
"from reflection cubemaps (0 to disabled)");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
prop = RNA_def_property(srna, "gi_show_irradiance", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SHOW_IRRADIANCE);