OpenGL场景渲染为黑色与阴影映射

OpenGL scene rendering as black with shadow mapping

本文关键字:黑色 阴影 映射 OpenGL      更新时间:2023-10-16

我正在尝试在我的OpenGL引擎中使用本教程实现阴影映射:http://www.fabiensanglard.net/shadowmapping/index.php

我没有任何问题,而制作阴影地图(我认为)。但是使用它,场景完全是阴影。


我渲染场景的方式如下:


  • 设置深度FBO

    GLuint sdepthtex;
    GLuint sframebuffer ;
    glGenTextures(1, &sdepthtex);
    glBindTexture(GL_TEXTURE_2D, sdepthtex);
    glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, 1024, 1024, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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_R_TO_TEXTURE);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, sdepthtex, 0);
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    {
     displayMessage("Error loading the Depth Framebuffer");
     return;
    }
    




  • 从光的角度制作ModelViewProjection矩阵,并将其存储在shadowMatrix变量中。

我使用的函数:

Matrix getMVPmatrix(vector3 position,vector3 lookat )
{
 glPushMatrix();
 double projection[16];
 double modelView[16];
 SDL_Surface*screen = SDL_GetVideoSurface();
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(FOVY,screen->w/screen->h,NEAR,FAR);
 glMatrixMode(GL_MODELVIEW);
 glEnable(GL_DEPTH_TEST);
 glLoadIdentity();
 gluLookAt(position.x,position.y,position.z,lookat.x,lookat.y,lookat.z,0,1,0);
 glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
 glGetDoublev(GL_PROJECTION_MATRIX, projection);
 Matrix m1(projection);
 Matrix m2(modelView);
 glPopMatrix();
 return m1*m2;
}



  • 在depth framebuffer中渲染场景。着色器:

顶点着色器:

uniform mat4 shadowMatrix;
void main()
{
    gl_Position = shadowMatrix*gl_Vertex;  
} 

片段着色器:

void main(void)
{
    gl_FragDepth = gl_FragCoord.z;
}


对于我的3个盒子场景,线性化的深度看起来像这样:

http://www.2shared.com/photo/IExy9aUo/Depth.html

所以我认为shadowMatrix和深度渲染是正确的。


  • 最后一关就是用阴影贴图绘制场景


顶点着色器:

varying vec4 ShadowCoord;
uniform mat4 shadowMatrix;
mat4 biasMatrix = mat4(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
void main (void)
{
    gl_TexCoord[0] =  gl_MultiTexCoord0;
    gl_FrontColor = gl_Color;
    gl_Position = ftransform();
    ShadowCoord = biasMatrix*shadowMatrix *vec4(gl_Vertex.xyz,1.0);
}


片段着色器:

uniform sampler2D tex;
uniform sampler2D shadowtex;//the non linearized depth texture we made in the 3rd step.
varying vec4 ShadowCoord;
float getShadowFactor(void)
{
    vec4 shadowCoordinateWdivide = ShadowCoord / ShadowCoord.w ;
    shadowCoordinateWdivide.z += 0.0005;
    float distanceFromLight = texture2D(shadowtex,shadowCoordinateWdivide.st).z;
    float shadow = 1.0;
    if (ShadowCoord.w > 0.0)
        shadow = distanceFromLight < shadowCoordinateWdivide.z ? 0.5 :1.0 ;
    return shadow ;
}
void main (void)
{
    gl_FragColor =texture2D(tex, gl_TexCoord[0].st);
    gl_FragColor.rgb *= getShadowFactor() ;//add shadows Here
}



结果呢?我所有的场景都被阴影了!



看起来你的代码在纹理设置和着色器之间存在不一致。在纹理设置代码中,你有如下代码:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);

GL_TEXTURE_COMPARE_FUNC不是GL_NONE时,你需要在你的着色器代码中使用阴影纹理采样器。但是在你的片段着色器中,你使用一个常规的采样器来处理这个纹理:

uniform sampler2D shadowtex;

这个需要更改为这个以与纹理设置兼容:

uniform sampler2DShadow shadowtex;

为了匹配类型,然后使用shadow2D()代替texture2D()对纹理进行采样。

另一种选择是将GL_TEXTURE_COMPARE_FUNC保持在默认值GL_NONE。这与使用sampler2D进行采样是一致的。