WIP: EEVEE-Next: Use luma weighted history blending #120867

Draft
Clément Foucault wants to merge 1 commits from fclem/blender:eevee-next-volume-flicker-reduction into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
3 changed files with 46 additions and 7 deletions

View File

@ -42,6 +42,21 @@ vec4 colorspace_scene_linear_from_YCoCg(vec4 ycocg_color)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Hyperbolic space
*
* Allow non linear accumulations that reduces flickering.
* Slide 20 of "High Quality Temporal Supersampling" by Brian Karis at SIGGRAPH 2014.
* To preserve more details in dark areas, we use a bigger bias (4 instead of 1).
* \{ */
float colorspace_hyperbolic_from_scene_linear(float value)
{
return 1.0 / (4.0 + value);
}
/** \} */
/**
* Clamp components to avoid black square artifacts if a pixel goes NaN or negative.
* Threshold is arbitrary.

View File

@ -37,9 +37,7 @@ vec4 film_texelfetch_as_YCoCg_opacity(sampler2D tx, ivec2 texel)
/* Returns a weight based on Luma to reduce the flickering introduced by high energy pixels. */
float film_luma_weight(float luma)
{
/* Slide 20 of "High Quality Temporal Supersampling" by Brian Karis at SIGGRAPH 2014. */
/* To preserve more details in dark areas, we use a bigger bias. */
return 1.0 / (4.0 + luma * uniform_buf.film.exposure_scale);
return colorspace_hyperbolic_from_scene_linear(luma * uniform_buf.film.exposure_scale);
}
/* -------------------------------------------------------------------- */

View File

@ -56,6 +56,35 @@ vec3 volume_scatter_light_eval(
#endif
float luma_weight(vec3 YCoCg_color)
{
float exposure = uniform_buf.film.exposure_scale;
return colorspace_hyperbolic_from_scene_linear(YCoCg_color.x * exposure);
}
void volume_history_blend(vec3 uvw_history, inout vec3 scattering, inout vec3 extinction)
{
vec3 scattering_history = texture(scattering_history_tx, uvw_history).rgb;
vec3 extinction_history = texture(extinction_history_tx, uvw_history).rgb;
/* Similar to film accumulation when using reprojection, use luma weighted blend in YCoCg space
* to reduce flickering. The difference is that we do not clamp to the neighborhood Bounding box
* as it would be very costly. */
scattering = colorspace_YCoCg_from_scene_linear(scattering);
scattering_history = colorspace_YCoCg_from_scene_linear(scattering_history);
float blend = uniform_buf.volumes.history_opacity;
float weight_src = luma_weight(scattering.x) * (blend);
float weight_dst = luma_weight(scattering_history.x) * (1.0 - blend);
float weight_sum = weight_src + weight_dst;
scattering = (scattering * weight_src + scattering_history * weight_dst) * safe_rcp(weight_sum);
scattering = colorspace_scene_linear_from_YCoCg(scattering);
/* Extinction doesn't produce flicker. Do simple blend. */
extinction = mix(extinction, extinction_history, blend);
}
void main()
{
ivec3 froxel = ivec3(gl_GlobalInvocationID);
@ -106,10 +135,7 @@ void main()
/* Temporal reprojection. */
vec3 uvw_history = volume_history_uvw_get(froxel);
if (uvw_history.x != -1.0) {
vec3 scattering_history = texture(scattering_history_tx, uvw_history).rgb;
vec3 extinction_history = texture(extinction_history_tx, uvw_history).rgb;
scattering = mix(scattering, scattering_history, uniform_buf.volumes.history_opacity);
extinction = mix(extinction, extinction_history, uniform_buf.volumes.history_opacity);
volume_history_blend(uvw_history, scattering, extinction);
}
}