Simple Shadow Mapping 最基本的SM。之前曾经被坑过,后来发现其实原理并不麻烦。就是 绘制深度图 加上 投影纹理映射 以及简单的比较就行了。
首先要获得深度图·其实要怎么获取·获取什么样的值(W-BUF或者Z-BUF)并没有太重要的关系·只要能有一张把光源当做摄像机所绘制出的深度图并保证比较时是一致的应该就可以了·
下面是简易的HLSL:
#pragma pack_matrix( row_major ) cbuffer Transforms{ float4x4 cb_WVP; }; struct VS_TO_PS{ float4 Pos : SV_POSITION; float2 Depth : TEXCOORD0; }; VS_TO_PS vs_main(float3 i_Pos : POSITION){ VS_TO_PS Out = (VS_TO_PS)0; Out.Pos = mul( float4(i_Pos, 1.0f), cb_WVP ); Out.Depth.xy = Out.Pos.zw; return Out; } float4 ps_main( VS_TO_PS i_n ) : SV_Target0{ return i_n.Depth.x / i_n.Depth.y; }
这里用这样的就够了·
#pragma pack_matrix( row_major ) cbuffer Transforms{ float4x4 cb_WVP; float4x4 cb_LightWVP; }; struct VS_TO_PS{ float4 Pos : SV_POSITION; float4 LightPos : TEXCOORD0; }; VS_TO_PS vs_main( float3 i_Pos : POSITION ){ VS_TO_PS Out = (VS_TO_PS)0; Out.Pos = mul( float4( i_Pos, 1.f ), cb_WVP ); Out.LightPos = mul( float4( i_Pos, 1.f ), cb_LightWVP ); return Out; } Texture2D DepthMap; SamplerState DepthMapSampler; static const float s_Offset = 0.00005f; static const float4 s_ShadowColor = float4(0.f, 0.f, 0.f, 0.5f); static const float4 s_OutColor = float4(0.f, 0.f, 0.f, 0.f); float4 ps_main( VS_TO_PS i_n ) : SV_Target0{ float3 t_ProjPos = i_n.LightPos.xyz / i_n.LightPos.w; t_ProjPos.x = +0.5 * t_ProjPos.x + 0.5f; t_ProjPos.y = -0.5 * t_ProjPos.y + 0.5f; float t_DepthMap = DepthMap.Sample( DepthMapSampler, t_ProjPos.xy ).r; float t_DepthScene = t_ProjPos.z - s_Offset; float4 t_OutColor = t_DepthMap >= t_DepthScene ? s_OutColor : s_ShadowColor; return t_OutColor; }
没什么特别的地方·只是把当前的位置变换到DepthMap的切线空间后与对应的值进行比较就可以了·
另外这里是用减去Offset值来处理Z-FIGHTING的问题·
不然就会这样·