109 lines
3.8 KiB
Plaintext
109 lines
3.8 KiB
Plaintext
float2 g_fResolution : register(c0);
|
|
float3 g_vViewPos : register(c2);
|
|
float g_fSplit : register(c23);
|
|
float4x4 g_mShadowVP : register(c24);
|
|
float3 g_vShadowViewPos : register(c28);
|
|
float3 g_vShadowViewDir : register(c29);
|
|
float4 g_fShadowMapScalingRes : register(c30);
|
|
|
|
sampler2D shadowMapSampler : register(s0);
|
|
sampler2D depthSampler : register(s1);
|
|
sampler2D ditherSampler : register(s2);
|
|
|
|
static float g_fRadius = 6.0f / 64.0f;
|
|
static float g_fBias = 4.0f / 64.0f;
|
|
static float g_fDepthBias = 16.0f / 64.0f;
|
|
static float g_fBiasFalloff = 1.5f / 64.0f;
|
|
static float g_fSharpness = 640.0f / 64.0f;
|
|
static float g_fBlurSharpness = 640.0f / 64.0f;
|
|
static float g_fDepthBlurSharpness = 16.0f / 64.0f;
|
|
|
|
static const float2 s_vShadowDisc[] = {
|
|
float2(-0.326212f, -0.40581f),
|
|
float2(-0.840144f, -0.07358f),
|
|
float2(-0.695914f, 0.457137f),
|
|
float2(-0.203345f, 0.620716f),
|
|
float2(0.96234f, -0.194983f),
|
|
float2(0.473434f, -0.480026f),
|
|
float2(0.519456f, 0.767022f),
|
|
float2(0.185461f, -0.893124f),
|
|
float2(0.507431f, 0.064425f),
|
|
float2(0.89642f, 0.412458f),
|
|
float2(-0.32194f, -0.932615f),
|
|
float2(-0.791559f, -0.59771f)
|
|
};
|
|
|
|
float4 ps_main(float2 TexCoord : TEXCOORD0, float3 EyeDir : TEXCOORD1) : COLOR0
|
|
{
|
|
// Compute eye space position
|
|
float fEyeDepth = tex2D(depthSampler, TexCoord).x;
|
|
float4 vEyePoint = float4(g_vViewPos + fEyeDepth * EyeDir, 1.0f);
|
|
|
|
// Transform eye point to shadow space
|
|
float4 vShadowCoord = mul(vEyePoint, g_mShadowVP);
|
|
vShadowCoord.z = dot(vEyePoint.xyz - g_vShadowViewPos, g_vShadowViewDir);
|
|
vShadowCoord.xy = vShadowCoord.xy * float2(.5f, -.5f)
|
|
+ vShadowCoord.w * (.5f + .5f / g_fShadowMapScalingRes.zw);
|
|
|
|
// Scale radius
|
|
float2 fScaledRadius = g_fRadius * g_fShadowMapScalingRes.xy;
|
|
|
|
// Transform to shadow map
|
|
float2 vShadowCoordProj = vShadowCoord.xy / vShadowCoord.w;
|
|
|
|
// Clip pixels outside shadow map
|
|
clip( float4(vShadowCoordProj, 1.0f - vShadowCoordProj) - fScaledRadius.xyxy );
|
|
|
|
// Compute sampling plane
|
|
float4 vShadowCoordDDX = ddx(vShadowCoord), vShadowCoordDDY = ddy(vShadowCoord);
|
|
float2 vShadowCoordDeltaDepth = float2(
|
|
vShadowCoordDDX.y * vShadowCoordDDY.z - vShadowCoordDDY.y * vShadowCoordDDX.z,
|
|
vShadowCoordDDY.x * vShadowCoordDDX.z - vShadowCoordDDX.x * vShadowCoordDDY.z )
|
|
/ (vShadowCoordDDY.x * vShadowCoordDDX.y - vShadowCoordDDX.x * vShadowCoordDDY.y);
|
|
vShadowCoordDeltaDepth = vShadowCoord.w * clamp(vShadowCoordDeltaDepth, -16.f, 16.f);
|
|
|
|
// Compute bias
|
|
float fAdaption = 1.f / (1.0f + g_fBiasFalloff * fEyeDepth);
|
|
float fAdaptedBias = g_fBias; // lerp(g_fDepthBias, g_fBias, fAdaption);
|
|
float fAdaptedBlurSharpness = lerp(g_fDepthBlurSharpness, g_fBlurSharpness, fAdaption);
|
|
|
|
// Apply bias
|
|
float fReferenceDepth = vShadowCoord.z - fAdaptedBias;
|
|
|
|
// Sample random 2D matrix
|
|
float4 vRotation = tex2D(ditherSampler, TexCoord * g_fResolution / 32.0f) * 2.0f - 1.0f;
|
|
float2x2 mRotation = float2x2(vRotation.xy, vRotation.zw);
|
|
|
|
float fShadow = -1.f;
|
|
float fSampleWeight = 1.f / 6;
|
|
|
|
// Sample
|
|
for(int i = 0; i < 12; )
|
|
{
|
|
float4 fSampleDepth;
|
|
|
|
// Vectorize occlusion code
|
|
[unroll] for(int j = 0; j < 4; j++, i++)
|
|
{
|
|
// Compute some point around this pixel
|
|
float2 vSampleOffset = fScaledRadius * mul(s_vShadowDisc[i], mRotation);
|
|
|
|
// Compute depth delta
|
|
float fSampleDeltaDepth = dot(vSampleOffset * vShadowCoordDeltaDepth, 1.f);
|
|
|
|
// Sample shadow map
|
|
fSampleDepth[j] = tex2D(shadowMapSampler, vShadowCoordProj + vSampleOffset).x - fSampleDeltaDepth;
|
|
}
|
|
|
|
// Compare shadow map depth with pixel depth
|
|
// (fSampleDepth < fReferenceDepth)
|
|
float4 fOcclusion = saturate(fAdaptedBlurSharpness * (fReferenceDepth - fSampleDepth));
|
|
|
|
// Sum up samples
|
|
fShadow += dot(fOcclusion, fSampleWeight);
|
|
}
|
|
|
|
// Write to intermediate buffer
|
|
return (1.0f - fShadow); // * float4(g_fSplit == float3(0, 1, 2) || g_fSplit == float3(3, 4, 5), 1.0f);
|
|
}
|