EEVEE: Planar Reflections: Fix regression

Fix regression with roughness not masking reflections when not using
Screen Space raytracing.

The trick was to only evaluate one planar per pixel, the one with
the most influence. This should not be too limiting since this is what
we do for SSR.

Also change evaluation order do not apply occlusion on planars probes.
This commit is contained in:
Clément Foucault 2021-02-20 16:54:06 +01:00
parent 274d7b87fd
commit 1a9fe57a9f
4 changed files with 37 additions and 30 deletions

View File

@ -84,13 +84,13 @@ void closure_Glossy_planar_eval(ClosureInputGlossy cl_in,
inout ClosureOutputGlossy cl_out)
{
#ifndef STEP_RESOLVE /* SSR already evaluates planar reflections. */
float attenuation = planar.attenuation * probe_attenuation_planar_normal_roughness(
planar.data, cl_in.N, cl_in.roughness);
vec3 probe_radiance = probe_evaluate_planar(
planar.id, planar.data, cl_common.P, cl_in.N, cl_common.V, cl_in.roughness);
cl_out.radiance += planar.attenuation * probe_radiance;
#else
/* HACK: Fix an issue with planar reflections still being counted inside the specular
* accumulator. This only works because we only use one Glossy closure in the resolve pass. */
cl_common.specular_accum += planar.attenuation;
cl_out.radiance = mix(cl_out.radiance, probe_radiance, attenuation);
#endif
}

View File

@ -64,13 +64,6 @@
out ClosureOutput##t3 out_##t3##_3) \
{ \
CLOSURE_EVAL_DECLARE(t0, t1, t2, t3); \
\
for (int i = 0; cl_common.specular_accum > 0.0 && i < prbNumPlanar && i < MAX_PLANAR; i++) { \
ClosurePlanarData planar = closure_planar_eval_init(i, cl_common); \
if (planar.attenuation > 1e-8) { \
CLOSURE_META_SUBROUTINE_DATA(planar_eval, planar, t0, t1, t2, t3); \
} \
} \
\
/* Starts at 1 because 0 is world cubemap. */ \
for (int i = 1; cl_common.specular_accum > 0.0 && i < prbNumRenderCube && i < MAX_PROBE; \
@ -90,6 +83,11 @@
} \
\
CLOSURE_META_SUBROUTINE(indirect_end, t0, t1, t2, t3); \
\
ClosurePlanarData planar = closure_planar_eval_init(cl_common); \
if (planar.attenuation > 1e-8) { \
CLOSURE_META_SUBROUTINE_DATA(planar_eval, planar, t0, t1, t2, t3); \
} \
\
for (int i = 0; i < laNumLight && i < MAX_LIGHT; i++) { \
ClosureLightData light = closure_light_eval_init(cl_common, i); \
@ -281,14 +279,20 @@ struct ClosurePlanarData {
float attenuation; /** Attenuation. */
};
ClosurePlanarData closure_planar_eval_init(int planar_id, inout ClosureEvalCommon cl_common)
ClosurePlanarData closure_planar_eval_init(inout ClosureEvalCommon cl_common)
{
ClosurePlanarData planar;
planar.id = planar_id;
planar.data = planars_data[planar_id];
planar.attenuation = probe_attenuation_planar(planar.data, cl_common.P, cl_common.N, 0.0);
planar.attenuation = min(planar.attenuation, cl_common.specular_accum);
cl_common.specular_accum -= planar.attenuation;
planar.attenuation = 0.0;
/* Find planar with the maximum weight. TODO(fclem) */
for (int i = 0; i < prbNumPlanar && i < MAX_PLANAR; i++) {
float attenuation = probe_attenuation_planar(planars_data[i], cl_common.P);
if (attenuation > planar.attenuation) {
planar.id = i;
planar.attenuation = attenuation;
planar.data = planars_data[i];
}
}
return planar;
}

View File

@ -182,7 +182,8 @@ void main()
for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; i++) {
PlanarData pd = planars_data[i];
float fade = probe_attenuation_planar(pd, W, wN, 0.0);
float fade = probe_attenuation_planar(pd, W);
fade *= probe_attenuation_planar_normal_roughness(pd, wN, 0.0);
if (fade > 0.5) {
/* Find view vector / reflection plane intersection. */
@ -525,7 +526,8 @@ void raytrace_resolve(ClosureInputGlossy cl_in,
for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; i++) {
pd = planars_data[i];
float fade = probe_attenuation_planar(pd, P, N, 0.0);
float fade = probe_attenuation_planar(pd, P);
fade *= probe_attenuation_planar_normal_roughness(pd, N, 0.0);
if (fade > 0.5) {
planar_index = float(i);

View File

@ -116,27 +116,28 @@ float probe_attenuation_cube(int pd_id, vec3 W)
return fac;
}
float probe_attenuation_planar(PlanarData pd, vec3 W, vec3 N, float roughness)
float probe_attenuation_planar(PlanarData pd, vec3 W)
{
/* Normal Facing */
float fac = saturate(dot(pd.pl_normal, N) * pd.pl_facing_scale + pd.pl_facing_bias);
/* Distance from plane */
fac *= saturate(abs(dot(pd.pl_plane_eq, vec4(W, 1.0))) * pd.pl_fade_scale + pd.pl_fade_bias);
float fac = saturate(abs(dot(pd.pl_plane_eq, vec4(W, 1.0))) * pd.pl_fade_scale +
pd.pl_fade_bias);
/* Fancy fast clipping calculation */
vec2 dist_to_clip;
dist_to_clip.x = dot(pd.pl_clip_pos_x, W);
dist_to_clip.y = dot(pd.pl_clip_pos_y, W);
/* compare and add all tests */
fac *= step(2.0, dot(step(pd.pl_clip_edges, dist_to_clip.xxyy), vec2(-1.0, 1.0).xyxy));
/* Decrease influence for high roughness */
fac *= saturate(1.0 - roughness * 10.0);
return fac;
}
float probe_attenuation_planar_normal_roughness(PlanarData pd, vec3 N, float roughness)
{
/* Normal Facing */
float fac = saturate(dot(pd.pl_normal, N) * pd.pl_facing_scale + pd.pl_facing_bias);
/* Decrease influence for high roughness */
return fac * saturate(1.0 - roughness * 10.0);
}
float probe_attenuation_grid(GridData gd, vec3 W, out vec3 localpos)
{
localpos = transform_point(gd.localmat, W);