2017-04-13 90 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

還有一些彼得平移的問題,但是這件事情我可以分開處理。