この記事では、バリアンス シャドウ マップを使用してシャドウをレンダリングする方法について説明します。
シーンをシャドウ マップにレンダリングするときは、深さと深さの 2 乗 (偏微分を使用したバイアス用に調整) を保存する必要があると書かれています。
float2 ComputeMoments(float Depth)
{
float2 Moments;
// First moment is the depth itself.
Moments.x = Depth;
// Compute partial derivatives of depth.
float dx = ddx(Depth);
float dy = ddy(Depth);
// Compute second moment over the pixel extents.
Moments.y = Depth*Depth + 0.25*(dx*dx + dy*dy);
return Moments;
}
次に、次のようにシャドウ マップに対して深度を確認します。
float ChebyshevUpperBound(float2 Moments, float t)
{
// One-tailed inequality valid if t > Moments.x
float p = (t <= Moments.x);
// Compute variance.
float Variance = Moments.y – (Moments.x*Moments.x);
Variance = max(Variance, g_MinVariance);
// Compute probabilistic upper bound.
float d = t – Moments.x;
float p_max = Variance / (Variance + d*d);
return max(p, p_max);
}
float ShadowContribution(float2 LightTexCoord, float DistanceToLight)
{
// Read the moments from the variance shadow map.
float2 Moments = texShadow.Sample(ShadowSampler, LightTexCoord).xy;
// Compute the Chebyshev upper bound.
return ChebyshevUpperBound(Moments, DistanceToLight);
}
この記事では、深さの 2 乗に偏りをまったく与えずに済む可能性があると述べています。分散を最小値に固定するようにしてください。本に付属のソース コードでは、バイアスを計算するコードがコメント アウトされており、最小の分散にクランプするように記述されています。
では、なぜ深さの 2 乗を最初に格納するのでしょうか? さらに、分散の計算をスキップして、常に最小分散を使用しないのはなぜですか? モーメント 1 が深さで、モーメント 2 が深さの 2 乗である場合、分散は常に 0 になるべきではありませんか?
float Variance = Moments.y – (Moments.x*Moments.x);