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

の問題は、あなたが見て取る必要があるいくつかの事ですので、ここで見つけるのは難しいです:あなたは、それ自身の方法で特別であるsamplerShadowを使用している

  1. は、あなたが設定する必要がありますCOMPARE_R_TO_TEXTUREとそれにはifステートメントは必要ありません。別の方法としては、sampler2Dを使用できますが、シェーダーでifステートメントを実行する必要があり、あなたが何をしたかのようなものが、COORDはvec2ないvec3

  2. するvec4テクスチャCOORDとtextureProjを使用することを検討しています。なぜなら、行列の乗算を使用して、光空間内の世界の位置を変換するほうがずっと簡単だからです。これは、最初にシャドーマップをレンダリングするのと同じ行列です。あなたの場合、それはこの値ですvec4 shadowCoord = ShadowTransform * pcolour;; textureProjと直接shadowCoordを使用してください。

+1

約2: 'sampler2DShadow'の代わりに' sampler2D'を使用すると、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

をいくつかのピーターパンの問題が残っていますが、それは私が個別に対処することができるものです。

関連する問題