阴影贴图工件

时间:2014-06-11 06:44:08

标签: directx hlsl shadow-mapping

我刚开始搞乱阴影贴图。我理解使用的算法。事情是我不能为我的生活找出我在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

任何帮助或见解都会受到学校项目的青睐。感谢

1 个答案:

答案 0 :(得分:2)

从深度缓冲区获得的值是浮点值,从0到1.您可能已经知道,浮点数不准确,您请求的小数点越多,它就越不准确,这就是您结束的地方有文物。

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

你可以做的另一件容易的事情是增加你正在绘制的纹理的大小,因为这会给你更多的像素,因此它将更准确地表示场景。

游戏引擎还可以做很多复杂的事情来改进阴影贴图工件,但是你可以写一本关于它的书,如果你真的想进入它,那么我建议你从{{{ 3}}