Not a bug per see but an undefined behavior according to the spec.
computeFallOff
is defined as:
float computeFallOff(float value, vec2 clipSpace, float frustumEdgeFalloff)
{
float mask = smoothstep(1.0 - frustumEdgeFalloff, 1.0, clamp(dot(clipSpace, clipSpace), 0., 1.));
return mix(value, 1.0, mask);
}
when frustumEdgeFalloff=0
, we get:
float mask = smoothstep(1.0, 1.0, clamp(dot(clipSpace, clipSpace), 0., 1.));
which is an undefined behavior according to smoothstep - OpenGL 4 Reference Pages :
Results are undefined if edge0 ≥ edge1
where edge0
= edge1
= 1.0
here (with those values, smoothstep
returns 0, which seems weird in itself, but makes the mix
works as expected).
The obvious workaround is to pass something like frustumEdgeFalloff = 0.000001
and not 0, but it would be better to skip all the calculations and simply returns value
. Maybe, in all functions calling computeFallOff
, a test should be done against frustumEdgeFalloff
and not call computeFallOff
when it is 0?
So, instead of:
return computeFallOff(darkness, clipSpace.xy, frustumEdgeFalloff);
do:
return frustumEdgeFalloff == 0 ? darkness : computeFallOff(darkness, clipSpace.xy, frustumEdgeFalloff);
in all shadow related functions.
I don’t know if the conditional test penalty is negated by not calling the function / not doing the falloff computation…