簡體   English   中英

從深度紋理采樣始終為0

[英]Sampling from depth texture always results 0

我試圖使用定向光使用opengl實現陰影映射。

我已經確認深度紋理正確渲染,如下所示: 深度紋理

為了進行視覺檢查,我還輸出了世界空間坐標,並轉換為燈光透視圖:

影子坐標

再次,似乎還可以。

但是,當我對深度紋理進行采樣時,請使用:

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

}

誰能發現這是哪里出了問題?

事實證明,我的采樣返回了正確的值。

真正的問題是由於渲染深度圖時剔除幾何體的背面,並處理了錯誤地對深度紋理進行采樣而產生的返回值,從而導致了非常細微的陰影痤瘡。

我將采樣功能更改為:

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之前。

完成此操作后,我得到以下結果: 最終渲染

仍然存在一些平移問題,但這是我可以單獨處理的問題。

像這樣的問題很難發現,因此您需要查看以下幾件事:

  1. 您正在使用samplerShadow具有特殊功能的samplerShadow ,需要設置COMPARE_R_TO_TEXTURE並且不需要if語句。 另外,您也可以使用sampler2D ,但是您需要在着色器中執行if語句,類似於您所做的事情,但是坐標必須是vec2而不是vec3

  2. 考慮使用帶有vec4紋理坐標的textureProj 因為使用矩陣乘法在光空間中變換世界位置要容易得多。 首先是用於渲染陰影貼圖的矩陣。 在您的情況下,此值為vec4 shadowCoord = ShadowTransform * pcolour; ; 直接將shadowCoordtextureProj一起textureProj

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM