首页 文章

从深度纹理采样总是得到0

提问于
浏览
1

我正在尝试使用opengl实现阴影贴图,使用定向光源 .

我已经确认正确渲染了深度纹理,如下所示:
depth texture

为了进行视觉检查,我还输出了世界空间坐标,转换为光透视:

shadow coords

再次,似乎没问题 .

但是,当我对深度纹理进行采样时,使用:

vec3 coord = vec3(shadowCoords.xy,shadowCoords.z/shadowCoords.w);
float depth = texture( shadowMap, coord);

我发现比较总是失败 . 如果我将 uniform sampler2DShadow shadowMap; 更改为 uniform sampler2D shadowMap; ,并使用 texture( shadowMap, coord.xy).r 直接对纹理进行采样,我会通过将此结果输出到屏幕来发现采样值始终为零 .

我创建了深度纹理,如下所示:

glGenTextures(1, &m_DepthTexture);
glBindTexture(GL_TEXTURE_2D, m_DepthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_DepthTexture, 0);

我的着色器代码如下(顶点):

#version 430
// Some drivers require the following
precision highp float;
layout (location = 0)in vec3 MSVertex;
layout (location = 4)in vec2 MSTexCoord;

out xferBlock
{
    vec3 VSVertex;
    vec2 VSTexCoord;
} outdata;

void main()
{
    outdata.VSVertex = MSVertex;
    outdata.VSTexCoord = MSTexCoord;
    gl_Position = vec4(MSVertex,1.0);
}

和片段着色器:

#version 430 core
// Some drivers require the following
precision highp float;

layout (location = 0) uniform sampler2D positionMap;
layout (location = 1) uniform sampler2D normalMap;
layout (location = 2) uniform sampler2D colourMap;
layout (location = 3) uniform sampler2D specularMap;
layout (location = 4) uniform sampler2DShadow shadowMap;

struct DirLightData
{
    vec4 colour;
    float intensity;
    vec4 direction;
};
uniform mat4 ShadowTransform;
uniform DirLightData dirLight;
out vec4 colour;
uniform vec3 WSCamPos;
in xferBlock
{
    vec3 VSVertex;
    vec2 VSTexCoord;
} indata;

vec3 computeLight(vec3 Ldirection, vec3 Vdirection, vec3 Lcolour, vec3 normal, float Lintensity, float specular)
{
    vec3 diffCol = Lcolour * max(0.0,dot(normalize(normal),-Ldirection));
    vec3 reflectVec = normalize(reflect(Ldirection,normal));
    float specFactor = max(dot(reflectVec,Vdirection),0);
    float specPow = pow(specFactor,specular*255.0);
    vec3 specCol = Lcolour * specPow;
    return (diffCol+specCol)*Lintensity;;
}
float computeOcclusion(vec4 shadowCoords)
{
    float vis = 1.0;
    vec3 coord = vec3(shadowCoords.xyz/shadowCoords.w);
    float depth = texture( shadowMap, vec3(coord.xy,coord.z+0.05));
    if (  depth < coord.z);
    {
        vis = 0.5;
    }
    return vis;
}
void main()
{
    vec4 pcolour = texture(positionMap, indata.VSTexCoord).rgba;
    vec4 ncolour = texture(normalMap, indata.VSTexCoord).rgba;
    vec4 dcolour = texture(colourMap, indata.VSTexCoord).rgba;
    vec4 scolour = texture(specularMap, indata.VSTexCoord).rgba;

    vec4 shadowCoord = ShadowTransform * pcolour;
    float visibility = computeOcclusion( shadowCoord );
    //float depth = texture(shadowMap, shadowCoord.xy).z;
    vec3 vToEye = WSCamPos - pcolour.xyz;
    vToEye = normalize(vToEye);
    vec3 outColour = vec3(0.0,0.0,0.0);

    outColour = computeLight(dirLight.direction.xyz,vToEye,dirLight.colour.rgb,ncolour.rgb,dirLight.intensity,scolour.r);
    colour = vec4(visibility*(dcolour.rgb*outColour),1.0);

}

任何人都可以发现这出错的地方吗?

2 回答

  • 3

    这样的问题很难发现,所以这里有一些你需要看的东西:

    • 您正在使用 samplerShadow ,这是特殊的,它需要设置COMPARE_R_TO_TEXTURE,并且您不需要 if 语句 . 或者你可以使用 sampler2D ,但你需要在着色器中做一个 if 语句,类似于你所做的,但是coord必须是 vec2 而不是 vec3

    • 考虑使用 textureProjvec4 纹理坐标 . 因为它's much easier to transform world position in light space using a matrix multiplication. It'是您用于首先渲染阴影贴图的相同矩阵 . 在你的情况下,它是这个值 vec4 shadowCoord = ShadowTransform * pcolour; ;直接使用 shadowCoordtextureProj .

  • 1

    事实证明我的采样返回了正确的值 .

    真正的问题是在渲染深度图时通过剔除几何体的背面而导致的非常细粒度的阴影痤疮,并且通过错误地采样深度纹理来处理返回值 .

    我将采样功能更改为:

    float computeOcclusion(vec4 shadowCoords)
    {
        vec3 coord = vec3(shadowCoords.xyz/shadowCoords.w);
        float depth = texture( shadowMap, vec3(coord.xy,coord.z+0.001));
        return depth;
    }
    

    并改变了我的深度渲染gl客户端代码,包括:

    glCullFace(GL_FRONT);
    

    在将几何体渲染到shadowMap之前 .

    完成后,我得到以下结果:
    final render

    还有一些peter平移问题,但这是我可以单独处理的事情 .

相关问题