Game Development Reference
In-Depth Information
If A is in the near field:
// Inpaint behind A using some arbitrary constant weight k
1.
w B = k
else if B is not in the near field:
// Obey occlusion; note that both r values are always negative in this case.
w B =max(0 , min(1 ,
|
r A
r B +1 . 5 | )) ·
( BA )
Gaussian
else :
// Avoid divide-by-zero if every sample pair hits this case.
w B = ε
In practice, we smooth the transitions by implementing the branches with lerps.
The relevant section of VVDoF blur.glsl in our demo source code is
float weight = 0.0;
float wNormal =
// Only consider mid- or background pixels (allows inpainting of the
// near field).
float (! inNearField(r_B)) *
// Only blur B over A if B is closer to the viewer (allow 0.5 pixels
// of slop and smooth the transition).
saturate(abs(r_A) - abs(r_B) + 1.5) *
// Stretch the Gaussian extent to the radius at pixel B.
gaussian[clamp( int ( float (abs(delta) * (GAUSSIAN_TAPS - 1)) /
(0.001 + abs(r_B * 0.5))), 0, GAUSSIAN_TAPS)];
weight = lerp(wNormal, 1.0, nearFieldness_A);
// far- + mid-field output
blurWeightSum += weight;
blurResult.rgb += blurInput.rgb * weight;
We compute the coverage value (alpha) for the separate near-field buffer in the
horizontal pass as
α B = min 1 ,
4
r B
maximum near-field blur
A
B
<r B ,
if
|
|
0
otherwise;
in code, this is somewhat more verbose:
float4 nearInput;
#if HORIZONTAL
nearInput.a = float (abs(delta) <= r_B) *