2017-04-13 86 views
1

我正在尝试使用opengl实现使用定向光的阴影映射。从深度纹理采样总是结果0

我已经证实,深度纹理正确呈现,像这样: 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); 

} 

任何人都可以哪里出问题了?

回答

1

像这样的问题是很难使这里发现的,你需要看看几件事情:

  1. 您使用的是samplerShadow这是它自己的方式特殊,你需要设置COMPARE_R_TO_TEXTURE并且你不需要这个if声明。或者您可以使用sampler2D,但你需要做一个if声明着色器,类似于你做了什么事,但坐标必须是vec2vec3

  2. 考虑使用textureProjvec4纹理坐标。因为使用矩阵乘法来改变光空间中的世界位置要容易得多。这与用于首先渲染阴影贴图的矩阵是相同的。在你的情况下,它的值是vec4 shadowCoord = ShadowTransform * pcolour;;直接与textureProj联系使用shadowCoord

+1

约2:如果您使用'sampler2D'而不是'sampler2DShadow',则不再使用PCF。 – BDL

+0

有两件事情:删除if语句并直接使用采样深度,并在渲染深度图之前调用glCullFace(GL_FRONT)。 看来,我有一个非常细晶粒阴影痤疮问题,这是不容易看到。 –

+0

虽然答案并不完全正确,但确实给了我思考并指引我走向正确的方向,所以谢谢。 –

3

原来,我的采样返回了正确的值。

真正的问题是在渲染深度贴图时剔除几何体的背面以及错误地处理从深度纹理采样的返回值所导致的非常细微的阴影痤疮。

我改变了采样功能:

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); 

并呈现几何形状的阴影贴图。

一旦这样做,我得到了以下结果: final render

还有一些彼得平移的问题,但是这件事情我可以分开处理。