2

我刚开始搞乱阴影贴图。我了解使用的算法。问题是我一生都无法弄清楚我在 HLSL 代码中搞砸的地方。这里是:

//These change
float4x4    worldViewProj;
float4x4    world;
texture     tex;

//These remain constant
float4x4    lightSpace;
float4x4    lightViewProj;
float4x4    textureBias;
texture     shadowMap;



sampler TexS = sampler_state
{
    Texture = <tex>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;
};

sampler TexShadow = sampler_state
{
    Texture = <shadowMap>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = LINEAR;
};

struct A2V
{   
    float3 posL : POSITION0;
    float2 texCo    : TEXCOORD0;
};

struct OutputVS
{
    float4 posH : POSITION0;
    float2 texCo    : TEXCOORD0;
    float4 posW : TEXCOORD2;
};

//Vertex Shader Depth Pass
OutputVS DepthVS(A2V IN)
{
    OutputVS OUT = (OutputVS)0;

    //Get screen coordinates in light space for texture map
    OUT.posH = mul(float4(IN.posL, 1.f), lightViewProj);
    //Get the depth by performing a perspective divide on the projected coordinates
    OUT.posW.x = OUT.posH.z/OUT.posH.w;
    return OUT;
}


//Pixel shader depth Pass
float4  DepthPS(OutputVS IN) : COLOR
{
    //Texture only uses red channel, just store it there
    return float4(IN.posW.x, 0, 0, 1);
}


//VertexShader Draw Pass
OutputVS DrawVS(A2V IN)
{
    OutputVS OUT = (OutputVS)0;

    //Get the screen coordinates for this pixel
    OUT.posH = mul(float4(IN.posL, 1.f), worldViewProj);
    //Send texture coordinates through
    OUT.texCo = IN.texCo;
    //Pass its world coordinates through
    OUT.posW = mul(float4(IN.posL, 1.f), world);
    return OUT;
}

//PixelShader Draw Pass
float4 DrawPS(OutputVS IN) : COLOR
{   
    //Get the pixels screen position in light space
    float4 texCoord = mul(IN.posW, lightViewProj);
    //Perform perspective divide to normalize coordinates [-1,1]
    //texCoord.x = texCoord.x/texCoord.w;
    //texCoord.y = texCoord.y/texCoord.w;
    //Multiply by texture bias to bring in range 0-1
    texCoord = mul(texCoord, textureBias);
    //Get corresponding depth value
    float prevDepth = tex2D(TexShadow, texCoord.xy);
    //Check if it is in shadow
    float4 posLight = mul(IN.posW, lightViewProj);
    float currDepth = posLight.z/posLight.w;
    if (currDepth >= prevDepth)
        return float4(0.f, 0.f, 0.f, 1.f);
    else
        return tex2D(TexS, IN.texCo);
}


//Effect info
technique ShadowMap
{
    pass p0
    {
        vertexShader = compile vs_2_0 DepthVS();
        pixelShader = compile ps_2_0 DepthPS();
    }

    pass p1
    {
        vertexShader = compile vs_2_0 DrawVS();
        pixelShader = compile ps_2_0 DrawPS();
    }
}

我已经验证我的所有矩阵都是正确的,并且深度图绘制正确。重写了所有处理此代码的 C++ 并使其更整洁,但我仍然遇到同样的问题。我目前没有混合阴影,只是将它们绘制为纯黑色,直到我可以正确绘制它们。灯光使用正交投影,因为它是定向灯光。我没有足够的信誉点来嵌入图像,但这里是 URL: 深度图 - http://i.imgur.com/T2nITid.png 程序输出 - http://i.imgur.com/ae3U3N0.png

任何帮助或见解将不胜感激,因为它适用于学校项目。谢谢

4

1 回答 1

2

您从深度缓冲区获得的值是从 0 到 1 的浮点值。您可能已经知道,浮点数不准确,您要求的小数位数越多,精度就越低,这就是您最终得到伪像的地方.

你可以做一些事情。最简单的方法是让投影矩阵中远近Z的值更接近,这样深度缓冲区就不会用那么多小数位来表示物体的距离。我通常发现 1-200 的值会给我一个相当好的准确结果。

您可以做的另一件简单的事情是增加您正在绘制的纹理的大小,因为这将为您提供更多像素,因此它将更准确地表示场景。

游戏引擎还可以做很多复杂的事情来改进阴影映射工件,但你可以写一本关于这方面的书,如果你真的想深入了解它,我建议你从博客开始。

于 2014-06-11T07:13:11.563 回答