Help with applying PCF to shadows (DirectX 11)

Started by
2 comments, last by adam7 3 years, 3 months ago

Hi, I'm trying to implement PCF into my shadows and I have got it working except I cant seem to properly apply it to my shadows. When I multiply the lighting calculation with the shadow factor from the pcf sampling, the result is this:

As you can see, the shadows do not have PCF applied except for a weird shadow which is applied on top of the scene based on the lights depth map, this is how the scene looks like when I dont multiply the light calculation with the shadow factor:

Now the scene looks fine, but the shadows do not have PCF.

Here is the first part of the pixel shader I am using, how can I fix this?

struct PixelInputType {
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
    float3 normal : NORMAL;
    float3 tangent : TANGENT;
    float3 binormal : BINORMAL;
    float4 lightViewPosition : TEXCOORD1;
    float3 lightPos : TEXCOORD2;
    float4 lightViewPosition2 : TEXCOORD3;
    float3 lightPos2 : TEXCOORD4;
};

float2 texOffset(int u, int v){
    return float2(u * 1.0f / 4096.0f, v * 1.0f / 4096.0f);
}

float4 ShadowPixelShader(PixelInputType input) : SV_TARGET{
    float bias;
    float4 color = float4(0.0f, 0.0f, 0.0f, 1.0f);
    float2 projectTexCoord;
    float depthValue;
    float lightDepthValue;
    float lightIntensity;
    float4 textureColor;

    float4 bumpMap;
    float3 bumpNormal;

    float shadowMapSize = 4096.0f;
    float shadowMapDX = 1.0f / shadowMapSize;
    float s0, s1, s2, s3;
    float r0, r1, r2, r3;
    float shadowFactor = 0.0f;
    float sum = 0.0f;
    float x, y;
    
    bias = 0.0005f;

    color = ambientColor;

    projectTexCoord.x = input.lightViewPosition.x / input.lightViewPosition.w / 2.0f + 0.5f;
    projectTexCoord.y = -input.lightViewPosition.y / input.lightViewPosition.w / 2.0f + 0.5f;

    bumpMap = normalMap.Sample(SampleTypeWrap, input.tex);
    bumpMap = (bumpMap * 2.0f) - 1.0f;
    bumpNormal = (bumpMap.x * input.tangent) + (bumpMap.y * input.binormal) + (bumpMap.z * input.normal);
    bumpNormal = normalize(bumpNormal);

    if ((saturate(projectTexCoord.x) == projectTexCoord.x) && (saturate(projectTexCoord.y) == projectTexCoord.y))
    {
        
        depthValue = depthMapTexture.Sample(SampleTypeClamp, projectTexCoord).r;
      
        lightDepthValue = input.lightViewPosition.z / input.lightViewPosition.w;

        lightDepthValue = lightDepthValue - bias;

        for (y = -1.5; y <= 1.5; y += 1.0) {
            for (x = -1.5; x <= 1.5; x += 1.0) {
                sum += depthMapTexture.SampleCmpLevelZero(SampleComp, input.lightPos.xy + texOffset(x, y), input.lightPos.z);
            }
        }

        shadowFactor = sum / 16.0f;

        if (lightDepthValue < depthValue){
            
            lightIntensity = saturate(dot(bumpNormal, input.lightPos));
       
            if (lightIntensity > 0.0f){
                color += (diffuseColor * lightIntensity) * shadowFactor;
            }
           
        }
   
    }
Advertisement

It looks like you're doing both PCF and regular shadow map sampling + comparison? You really only want to do one or the other, it doesn't make sense to combine them. Just take out the parts where you sample depthValue and compare it to lightDepthValue, and instead just multiply your lighting by shadowFactor.

Your other issue seems to be that you're using totally different coordinates for your PCF sampling compared to your “regular” shadow map sampling. Your x/y offsets you're applying are also incorrect: the input UV value for SampleCmpLevelZero are in the [0, 1] range, just like any other texture. So if you want to apply a 1.5 texel offset, then the offset you want is 1.5 / ShadowMapResolution. As an example, look at this shader code: it's doing more complex things than your simple PCF loop, but you can see how the offset is multiplied with the texel size before applying it to the shadow map UV coordinate.

@MJP Thanks for your reply. You were right, I was sampling using the wrong coorddinates. I have fixed it now, thanks!

This topic is closed to new replies.

Advertisement