シャドウマップの改良 -側面のジャギーを軽減-
前回HLSLで影の描画 -シャドウマップ- - while( c++ );のシャドウマップを使った影の描画を、もう少しキレイにしてみます。
特にライトへのベクトルと面の法線ベクトルのなす角が90度に近い部分の汚い影ですね。
とりあえず、らしく見えれば良いということで。
考え方
- ライトベクトルと法線ベクトルのなす角が垂直に近づけば、影も薄くなる。
- L・N = 影の濃さ
- 頂点シェーダ内のL・Nをピクセルシェーダに渡して、影を描画するときにピクセルの色に1-L・Nを掛ける。
- 2乗、3乗するとキレイ(線形より曲線)
shadow.fx
struct VertexOutput { float4 pos : POSITION; float4 color : COLOR0; float4 shadowmap : TEXCOORD0; float4 color2 : TEXCOORD1; //w=影の濃さ }; VertexOutput VS( float4 pos : POSITION, float3 normal : NORMAL ) { VertexOutput output = ( VertexOutput )0; float4 p = mul( pos, M_world ); output.pos = mul( p, M_view_proj ); float3 n = mul( normal, M_world ); n = normalize( n ); float k = max( dot( light_dir.xyz, n ), 0.0f ); float4 color = k * light_diffuse * material_diffuse; color += light_ambient * material_ambient; output.color = color; //影の濃さ(適当に3乗してみた) output.color2.w = k * k * k * 0.6f; p = mul( pos, M_world ); p = mul( p, M_lightview_proj ); output.shadowmap = p; return output; } float4 PS( VertexOutput input ) : COLOR { float w = 1.0f / input.shadowmap.w; float2 tex; tex.x = ( 1.0f + input.shadowmap.x * w ) * 0.5f; tex.y = ( 1.0f - input.shadowmap.y * w ) * 0.5f; float z = tex2D( shadow_sampler, tex ).x; float color = input.color; if( input.shadowmap.z * w > z + bias ) color = color * ( 1.0f - input.color2.w );//影の濃さを掛ける return color; }
かなり適当です。
多分もっと一般的な方法があるのではないかと。
自力ではこの程度の方法しか思いつきませんでした。。。