1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
// Calculate the 2D screenposition of a position vectore
float2 PostProjToScreen(float4 position)
{
float2 screenPos = position.xy / position.w;
return 0.5f * (float2(screenPos.x, -screenPos.y) + 1);
}
// Calculate the size of one half of a pixel, to convert
// between texels and pixels
float2 HalfPixel()
{
return 0.5f / float2(ViewportWidth, ViewportHeight);
}
float SampleShadowDepthMap(float2 UV)
{
if (UV.x < 0 || UV.x > 1 || UV.y < 0 || UV.y > 1)
return 1;
return tex2D(ShadowDepthSampler, UV).r;
}
VertexShaderOutput SpotLightVertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, World);
float4x4 viewProjection = mul(View, Projection);
output.Position = mul(worldPosition, viewProjection);
output.Position3D = output.Position;
return output;
}
float4 SpotLightPixelShaderFunction(VertexShaderOutput input) : COLOR0
{
// Find the pixel coordinates of the input position in the depth
// and normal textures
float2 texCoord = PostProjToScreen(input.Position3D) + HalfPixel();
// Extract the depth for this pixel from the depth map
float4 depth = tex2D(DepthSampler, texCoord);
// Recreate the position with the UV coordinates and depth value
float4 position;
position.x = texCoord.x * 2 - 1;
position.y = (1 - texCoord.y) * 2 - 1;
position.z = depth.r;
position.w = 1.0f;
// Transform position from screen space to world space
position = mul(position, InverseViewProjection);
position.xyz /= position.w;
// Extract the normal from the normal map and move from
// 0 to 1 range to -1 to 1 range
float4 normal = (tex2D(NormalSampler, texCoord) - .5) * 2;
// Compute the attenuation
float atten = ...
// Compute the spot attenuation factor
float spotAtten = ...
// Get shadow
float4x4 shadowViewProjection = mul(ShadowView, ShadowProjection);
float4 ShadowPosition = mul(position, shadowViewProjection);
float2 shadowTexCoord = PostProjToScreen(ShadowPosition) + ( 0.5f / float2(2048, 2048));
float mapDepth = SampleShadowDepthMap(shadowTexCoord); // Depth of the position in shadow map
float realDepth = ShadowPosition.z / 5000; // Depth of position from spot light view
float shadow = 1;
if (realDepth > mapDepth)
shadow = 0;
return SpotLightDiffuseColor * nDotl * atten * spotAtten * shadow;
} |
Partager