Hey guys!
I am currently trying to get the code from MJP (aka Matt) on PCF shadow maps working. When trying to compile the adopted code, the compilation fails with
- forced to unroll loop, but unrolling failed
- unable to unroll loop, loop does not appear to terminate in a timely manner (36 iterations), use the [unroll(n)] attribute to force an exact higher number
Since my shader abilities are slim to none I am stuck here , the code did compile well on XNA, though.
Has any shader guru here some suggestions on how and why to fix this?
Full shader code:
int param_filterSize;
float4x4 param_worldMatrix;
float4x4 param_viewProjectionMatrix;
float4x4 param_inverseViewMatrix;
float param_farClip;
float2 param_shadowMapSize;
float param_BIAS;
float2 param_occlusionTextureSize;
float3 param_frustumCornersVS[4];
float4x4 param_lightViewProjectionMatrix;
texture param_depthTexture;
texture param_shadowMap;
sampler2D DepthTextureSampler = sampler_state
{
Texture = <param_depthTexture>;
MinFilter = point;
MagFilter = point;
MipFilter = none;
};
sampler2D ShadowMapSampler = sampler_state
{
Texture = <param_shadowMap>;
MinFilter = point;
MagFilter = point;
MipFilter = none;
};
// Define VS input
struct VSIn
{
float3 Position : POSITION0;
float3 TextureCoordsAndCornerIndex : TEXCOORD0;
};
// Define VS output and therefor PS input
struct VSOut
{
float4 PositionCS : POSITION0;
float2 TextureCoords : TEXCOORD0;
float3 FrustumCornerVS : TEXCOORD1;
};
// Define PS output
struct PSOut
{
float4 Color : COLOR0;
};
/**************************************************
Calculates the shadow term using PCF soft-shadowing
**************************************************/
float CalcShadowTermSoftPCF(float fLightDepth, float2 vShadowTexCoord, int iSqrtSamples)
{
float fShadowTerm = 0.0f;
float fRadius = (iSqrtSamples - 1.0f) / 2;
float fWeightAccum = 0.0f;
for (float y = -fRadius; y <= fRadius; y++)
{
for (float x = -fRadius; x <= fRadius; x++)
{
float2 vOffset = 0;
vOffset = float2(x, y);
vOffset /= param_shadowMapSize;
float2 vSamplePoint = vShadowTexCoord + vOffset;
float fDepth = tex2D(ShadowMapSampler, vSamplePoint).x;
float fSample = (fLightDepth <= fDepth + param_BIAS);
// Edge tap smoothing float xWeight = 1; float yWeight = 1;
if (x == -fRadius) xWeight = 1 - frac(vShadowTexCoord.x * param_shadowMapSize.x); else if (x == fRadius) xWeight = frac(vShadowTexCoord.x * param_shadowMapSize.x);
if (y == -fRadius) yWeight = 1 - frac(vShadowTexCoord.y * param_shadowMapSize.y); else if (y == fRadius) yWeight = frac(vShadowTexCoord.y * param_shadowMapSize.y);
fShadowTerm += fSample * xWeight * yWeight; fWeightAccum = xWeight * yWeight; }
}
fShadowTerm /= (iSqrtSamples * iSqrtSamples);
fShadowTerm *= 1.55f;
return fShadowTerm;
}
/**************************************************
Vertex shader.
**************************************************/
VSOut MainVS(VSIn input)
{
VSOut output;// Offset the position by half a pixel to correctly align texels to pixels
output.PositionCS.x = input.Position.x - (1.0f / param_occlusionTextureSize.x);
output.PositionCS.y = input.Position.y + (1.0f / param_occlusionTextureSize.y);
output.PositionCS.z = input.Position.z;
output.PositionCS.w = 1.0f;
// Pass along the texture coordiante and the position of the frustum corner
output.TextureCoords = input.TextureCoordsAndCornerIndex.xy;
output.FrustumCornerVS = param_frustumCornersVS[input.TextureCoordsAndCornerIndex.z];return output;
}
/**************************************************
Pixel shader.
**************************************************/
PSOut MainPS(VSOut input)
{
PSOut output;
// Reconstruct view-space position from the depth buffer
float fPixelDepth = tex2D(DepthTextureSampler, input.TextureCoords).r;
float4 vPositionVS = float4(fPixelDepth * input.FrustumCornerVS, 1.0f);
// Determine the depth of the pixel with respect to the light
float4x4 matViewToLightViewProj = mul(param_inverseViewMatrix, param_lightViewProjectionMatrix);
float4 vPositionLightCS = mul(vPositionVS, matViewToLightViewProj);
float fLightDepth = vPositionLightCS.z / vPositionLightCS.w;
// Transform from light space to shadow map texture space.
float2 vShadowTexCoord = 0.5 * vPositionLightCS.xy / vPositionLightCS.w + float2(0.5f, 0.5f);
vShadowTexCoord.y = 1.0f - vShadowTexCoord.y;
// Offset the coordinate by half a texel so we sample it correctly
vShadowTexCoord += (0.5f / param_shadowMapSize);
// Get the shadow occlusion factor and output it
float fShadowTerm = 0;
if (param_filterSize == 2)
// fShadowTerm = CalcShadowTermPCF(fLightDepth, vShadowTexCoord);
fShadowTerm = CalcShadowTermSoftPCF(fLightDepth, vShadowTexCoord, param_filterSize);
else
fShadowTerm = CalcShadowTermSoftPCF(fLightDepth, vShadowTexCoord, param_filterSize);
output.Color = float4(fShadowTerm, 1, 1, 1);
return output;
}
/**************************************************
Techniques
- CreateShadowTerm
*************************************************/
technique CreateShadowTerm
{
pass p0
{
/
ZWriteEnable = false;
ZEnable = false;
AlphaBlendEnable = false;
CullMode = NONE;
*/
VertexShader = compile vs_4_0_level_9_1 MainVS(); PixelShader = compile ps_4_0_level_9_1 MainPS();
}
}