NVIDIA SDK 8.0のサンプルコードにソフトシャドウがあったので、そのWhitepaper を読んで実装しました。
で、いつものようにプログラムです。
スライダーを動かすと、ボケ具合が変わります。
ソースには、いつものように適当にファイルが入っています。 大事なファイルは次のものです。
| main.cpp | アプリケーションのソース |
| hlsl.fx | シェーダプログラム |
ガウスぼかしをするときのように適当に(12点)周辺をサンプリングして、それぞれのシャドウバッファの値と現在の深度値との比較をしてその平均をとります。
0177: float4 ShadowMap12PS( VS_OUTPUT_SHADOW In ) : COLOR
0178: {
0179: float2 t = In.ShadowMap.xy / In.ShadowMap.w;
0180: float2 t0 = t + g_Offset[ 0].xy;
0181: float2 t1 = t + g_Offset[ 1].xy;
0182: float2 t2 = t + g_Offset[ 2].xy;
0183: float2 t3 = t + g_Offset[ 3].xy;
0184: float2 t4 = t + g_Offset[ 4].xy;
0185: float2 t5 = t + g_Offset[ 5].xy;
0186: float2 t6 = t + g_Offset[ 6].xy;
0187: float2 t7 = t + g_Offset[ 7].xy;
0188: float2 t8 = t + g_Offset[ 8].xy;
0189: float2 t9 = t + g_Offset[ 9].xy;
0190: float2 ta = t + g_Offset[10].xy;
0191: float2 tb = t + g_Offset[11].xy;
0192:
0193: float shadow_map0 = tex2D( ShadowSampler, t0 ).x;
0194: float shadow_map1 = tex2D( ShadowSampler, t1 ).x;
0195: float shadow_map2 = tex2D( ShadowSampler, t2 ).x;
0196: float shadow_map3 = tex2D( ShadowSampler, t3 ).x;
0197: float shadow_map4 = tex2D( ShadowSampler, t4 ).x;
0198: float shadow_map5 = tex2D( ShadowSampler, t5 ).x;
0199: float shadow_map6 = tex2D( ShadowSampler, t6 ).x;
0200: float shadow_map7 = tex2D( ShadowSampler, t7 ).x;
0201: float shadow_map8 = tex2D( ShadowSampler, t8 ).x;
0202: float shadow_map9 = tex2D( ShadowSampler, t9 ).x;
0203: float shadow_mapa = tex2D( ShadowSampler, ta ).x;
0204: float shadow_mapb = tex2D( ShadowSampler, tb ).x;
0205:
0206: float depth = In.Pos.z / In.Pos.w - 0.003;
0207: float shade = (( shadow_map0 < depth ) ? 0 : 1)
0208: + (( shadow_map1 < depth ) ? 0 : 1)
0209: + (( shadow_map2 < depth ) ? 0 : 1)
0210: + (( shadow_map3 < depth ) ? 0 : 1)
0211: + (( shadow_map4 < depth ) ? 0 : 1)
0212: + (( shadow_map5 < depth ) ? 0 : 1)
0213: + (( shadow_map6 < depth ) ? 0 : 1)
0214: + (( shadow_map7 < depth ) ? 0 : 1)
0215: + (( shadow_map8 < depth ) ? 0 : 1)
0216: + (( shadow_map9 < depth ) ? 0 : 1)
0217: + (( shadow_mapa < depth ) ? 0 : 1)
0218: + (( shadow_mapb < depth ) ? 0 : 1);
0219:
0220: const float ambient = 0.3;
0221:
0222: return tex2D( Sampler, In.TextureUV )
0223: * (((1.0-ambient)/12.0) * shade * In.Diffuse + ambient);
0224: }
g_Offset[i] に、ガウス型の分布を入れています(係数は、ATIの数値そのままなので、ShaderX2でも見てください)。
境界部分もぼけるので、使い道は限られるか。