ShadowMap peter-panning and wrong direction I am creating Forward-Rendering DX11 engine and I have some troubles with shadow-mapping algorithm as it doesn't work as supposed.





As you can see - shadow is peter-panning and looks totally not releated. Basically as I have tested, comparision in PixelShader has no effect. Only projected shadowmap texture is returned, if statement doesn't do anything.

MyVertexShader:

PixelInputType ColorVertexShader(VertexInputType input)
{
    PixelInputType output;
    float4 worldPosition;

    input.position.w = 1.0f;
    worldPosition = mul(input.position, worldMatrix);
    output.normal = input.normal;

    // Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);

    //Calculate object seen by light
    output.lightViewPosition = mul(input.position, worldMatrix);
    output.lightViewPosition = mul(output.lightViewPosition, g_lightViewMatrix);
    output.lightViewPosition = mul(output.lightViewPosition, g_lightProjectionMatrix);

    //Calculate light-object vector
    output.lightPos = g_lightPosition.xyz - worldPosition.xyz;
    output.lightPos = normalize(output.lightPos);

    return output;
}


MyPixelShader:

float4 ColorPixelShader(PixelInputType input) : SV_TARGET
{
    float4 color = float4(0.0, 0.0, 0.0, 1.0);
    float depthValue;
    float lightDepthValue;
    float bias = 0.001f;
    float4 textureColor = float4(1.0, 1.0, 1.0, 1.0);
    float4 ambientColor = float4(1.0, 0.0, 1.0, 1.0);
    float2 tex;
    float lightIntensity = 0.0f;

    input.lightViewPosition.xyz /= input.lightViewPosition.w;

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

    return depthValue = shadowMap.Sample(SampleType, tex).r;
    color = float4(depthValue, depthValue, depthValue, 1.0f);

    lightDepthValue = input.lightViewPosition.z;// / input.lightViewPosition.w;
    lightDepthValue = lightDepthValue - bias;
    if(lightDepthValue &lt; depthValue)
    {
        lightIntensity = saturate(dot(input.normal, input.lightPos));

        if(lightIntensity &gt; 0.0f)
        {
            // Determine the final diffuse color based on the diffuse color and the amount of light intensity.
            color += (ambientColor * lightIntensity);

            // Saturate the final light color.
            color = saturate(color);
        }
    }
    return color;
}
I found out that simply removing minus sign in shader in converting coords to [0, 1] solved direction problem. But scale is still off - here is an example:



void LightClass::GenerateViewMatrix()
{
    XMVECTOR eyePos = { m_position.x, m_position.y, m_position.z };
    XMVECTOR focusPos = { m_lookAt.x, m_lookAt.y, m_lookAt.z };
    XMVECTOR upVec = { 0, 1, 0 };

    m_viewMatrix = XMMatrixLookAtLH(eyePos, focusPos, upVec);
}

void LightClass::GenerateProjectionMatrix(float screenDepth, float screenNear)
{
    float fieldOfView = (float)3.14f / 2.0f;
    float screenAspect = 16.0f / 9.0f;

    m_projectionMatrix = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, screenNear, screenDepth);
}


Edit [Actual solution - ignore previous posts]:

I followed PaulHK solution (thanks, it's second time you've helped me) about checking once again View/Projection matrix. Basically my calculations were wrong. I debugged my convertions from model to lightspace and changed Vertex Shader from:

output.lightViewPosition = mul(input.position, worldMatrix);
output.lightViewPosition = mul(output.lightViewPosition, g_lightViewMatrix);
output.lightViewPosition = mul(output.lightViewPosition, g_lightProjectionMatrix);


To correct:

matrix lightViewProj = mul(g_lightProjectionMatrix, g_lightViewMatrix);
output.lightViewPosition = mul(input.position, lightViewProj);


That simple changed fixed my results. With simple Pixel shader code below I am getting this results:

input.lightViewPosition.xyz /= input.lightViewPosition.w;

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

depthValue = shadowMap.Sample(SampleType, tex).r;
return color = float4(depthValue, depthValue, depthValue, 1.0f);



However, even if it seems correct, my suspicion is that I need to compare my shadowmap to light Z-buffer so I modified my Pixel Shader and added little tint:

input.lightViewPosition.xyz /= input.lightViewPosition.w;

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

depthValue = shadowMap.Sample(SampleType, tex).r;
color = float4(depthValue, depthValue, depthValue, 1.0f);

lightDepthValue = input.lightViewPosition.z - bias;
if(lightDepthValue &lt; depthValue)
{
    lightIntensity = saturate(dot(input.normal, input.lightPos));

    if(lightIntensity &gt; 0.0f)
    {
        // Determine the final diffuse color based on the diffuse color and the amount of light intensity.
        color += (ambientColor * lightIntensity);

        // Saturate the final light color.
        color = saturate(color);
    }
}
return color;


I may not be right, but without this checking, you would get errors with more complicated shadows. Because my previous PixelShader code basically just project shadowmap on plane without any actual depth checking. Therefore it would lay shadowmap on everything it can without even checking if that's correct.