2017-04-13 2 views
1

Je tente d'implémenter la cartographie d'ombre en utilisant opengl, en utilisant une lumière directionnelle.L'échantillonnage à partir de la texture de la profondeur donne toujours 0

Je confirme que la texture de profondeur est rendu correctement, comme ceci: depth texture

Et pour effectuer une inspection visuelle, je également sortie les coordonnées spatiales du monde, transformées à la perspective lumière:

shadow coords

Encore une fois, ça semble aller.

Cependant, quand j'échantillon, la texture de profondeur, en utilisant:

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

Je trouve que la comparaison échoue toujours. Si je change uniform sampler2DShadow shadowMap; en uniform sampler2D shadowMap;, et échantillonne la texture directement en utilisant texture(shadowMap, coord.xy).r, je trouve que la valeur échantillonnée est toujours nulle, en produisant ce résultat à l'écran.

J'ai créé la texture de profondeur comme ceci:

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

et mon code shader est la suivante (sommet):

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

et fragment shader:

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

} 

Quelqu'un peut-il endroit où cela ne va pas?

Répondre

1

Les problèmes de ce genre sont difficiles à repérer alors voici quelques choses que vous devez jeter un oeil à:

  1. Vous utilisez un samplerShadow qui est spécial dans sa propre façon, vous devez définir COMPARE_R_TO_TEXTURE et avec cela, vous n'avez pas besoin de cette déclaration if. Vous pouvez également utiliser sampler2D, mais vous devez faire une déclaration if dans le shader, quelque chose de semblable à ce que vous avez fait, mais le coord doit être vec2 pas vec3

  2. envisager d'utiliser textureProj avec vec4 coord de texture. parce qu'il est beaucoup plus facile de transformer la position du monde dans l'espace lumineux en utilisant une multiplication matricielle. C'est la même matrice que vous utilisez pour le rendu de la carte d'ombre en premier lieu. Dans votre cas, c'est cette valeur vec4 shadowCoord = ShadowTransform * pcolour;; utiliser shadowCoord directement avec textureProj.

+1

A propos de 2: Si vous utilisez 'sampler2D' à la place de' sampler2DShadow', vous n'utiliserez plus PCF. – BDL

+0

Deux choses ont fonctionné: supprimer l'instruction if et utiliser directement la profondeur échantillonnée, et appeler glCullFace (GL_FRONT) avant de rendre la carte de profondeur. Il semble que j'ai eu un problème d'acné d'ombre de grain très fin, qui n'était pas facile à voir. –

+0

Même si la réponse n'était pas * exactement * juste, elle m'a donné matière à réflexion et m'a orienté dans la bonne direction, alors merci. –

3

Il s'est avéré que mon échantillonnage renvoyait la valeur correcte. Le véritable problème était une acné d'ombre grainée très fine causée par l'élimination des faces arrière de la géométrie lors du rendu de la carte de profondeur, et le traitement de la valeur de retour de l'échantillonnage de la texture de profondeur incorrectement.

j'ai changé la fonction d'échantillonnage:

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

et ils ont changé mon rendu profondeur code client gl inclure:

glCullFace(GL_FRONT); 

Avant de rendre la géométrie à l'shadowmap.

Une fois que cela a été fait, je me suis le résultat suivant: final render

Il y a encore quelques problèmes panning peter, mais c'est quelque chose que je peux traiter séparément.