C++ 尝试渲染阴影贴图时,OpenGL场景渲染为黑色

C++ 尝试渲染阴影贴图时,OpenGL场景渲染为黑色,c++,opengl,matrix,glsl,shadow-mapping,C++,Opengl,Matrix,Glsl,Shadow Mapping,我目前正在我的应用程序中实现阴影贴图支持,我一直在遵循此链接中演示的过程: 然而,我注意到他正在使用纹理矩阵投影阴影贴图,但我想不必使用纹理矩阵 渲染场景的方式如下所示: 为深度纹理设置FBO 从灯光角度设置投影和模型视图矩阵 禁用颜色遮罩并渲染场景 通过执行以下操作设置阴影矩阵:阴影矩阵=偏移*lightProjectionMatrix*lightModelViewMatrix 将阴影矩阵与实际摄影机modelview矩阵的逆矩阵相乘 将shadowMatrix作为mat4统一变量发送到着色器

我目前正在我的应用程序中实现阴影贴图支持,我一直在遵循此链接中演示的过程:

然而,我注意到他正在使用纹理矩阵投影阴影贴图,但我想不必使用纹理矩阵

渲染场景的方式如下所示:

为深度纹理设置FBO 从灯光角度设置投影和模型视图矩阵 禁用颜色遮罩并渲染场景 通过执行以下操作设置阴影矩阵:阴影矩阵=偏移*lightProjectionMatrix*lightModelViewMatrix 将阴影矩阵与实际摄影机modelview矩阵的逆矩阵相乘 将shadowMatrix作为mat4统一变量发送到着色器 在我的顶点着色器中,我有一个可变的vec4 shadowCoord变量,它是通过将shadowMatrix均匀乘以gl_ModelViewMatrix和gl_vertex shadowCoord=shadowMatrix*gl_ModelViewMatrix*gl_vertex计算得出的

片段着色器与上面链接中提到的完全相同。结果显示场景完全为黑色或阴影设置为的任何阴影/颜色

我假设在将偏移、lightProjectionMatrix、lightModelViewMatrix与相机的modelview矩阵的逆矩阵相乘时,我做错了什么。有人能指出我做错了什么吗

编辑:我希望有人可以识别问题,而不必粘贴代码,因为复杂性,但我会尝试粘贴我可以无论如何。很抱歉,如果代码乱七八糟,为了简单起见,我不得不去掉很多代码:

int vp[4];
kexMatrix lightProj, lightMV;
kexCamera tmpCam;

renderBackend.SetColorMask(0);

// save actual camera viewport
glGetIntegerv(GL_VIEWPORT, vp);

// set viewport to framebuffer object size (512x512)
// smFbo is my framebuffer class used for the shadowmap/depth
glViewport(0, 0, smFbo.Width(), smFbo.Height());

// bind framebuffer
smFbo.Bind();
glClear(GL_DEPTH_BUFFER_BIT);

// setup temp. camera for light source
tmpCam.SetOrigin(kexVec3(-2048, 860, 450)); // x, y, z with y being up, and z being forward/back
tmpCam.SetAngles(kexAngle(1.0f, 0.5f, 0.0f)); // yaw, pitch and roll in radians
tmpCam.SetupMatrices();

lightProj = tmpCam.Projection();
lightMV = tmpCam.ModelView();

// setup matrices for OGL
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(lightProj.ToFloatPtr());
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(lightMV.ToFloatPtr());

bShadowPass = true;
// note that each static actor object has its own matrix so before drawing I do:
// glPushMatrix();
// glMultMatrixf(actor->Matrix());
// draw and pop matrix
DrawStaticActors();
bShadowPass = false;

// unbind framebuffer object and restore viewport
smFbo.UnBind();
glViewport(vp[0], vp[1], vp[2], vp[3]);
renderBackend.SetColorMask(1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

kexMatrix bias;

bias.vectors[0].Set(0.5f, 0, 0, 0);
bias.vectors[1].Set(0, 0.5f, 0, 0);
bias.vectors[2].Set(0, 0, 0.5f, 0);
bias.vectors[3].Set(0.5f, 0.5f, 0.5f, 1.0f);

// setup matrices from world camera. handles gl projection/modelview setup as well
SetCameraView(world->Camera());

// shadowmap matrix for GLSL shader
shadowMatrix = bias * lightProj * lightMV * kexMatrix::Invert(world->Camera()->ModelView());

// draw scene as normal and sets up the shader
// shadowMap sampler2D uniform is binded to 1
// also calls smFbo.BindImage() which binds the actual texture to texture unit # 1
// shadowMatrix is also sent as uniform to shader
DrawStaticActors();
深度帧缓冲区设置

// texture
glGenTextures(1, &fboTexId);
glBindTexture(GL_TEXTURE_2D, fboTexId);
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_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
              0,
              GL_DEPTH_COMPONENT,
              fboWidth,
              fboHeight,
              0,
              GL_DEPTH_COMPONENT,
              GL_FLOAT,
              0);

// framebuffer
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
                        GL_DEPTH_ATTACHMENT_EXT,
                        GL_TEXTURE_2D,
                        fboTexId,
                        0);

CheckStatus();

glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
FBO绑定函数

glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
glReadBuffer(GL_NONE);
glDrawBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
FBO解绑函数

glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
glReadBuffer(GL_NONE);
glDrawBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
FBO绑定镜像函数

int unit = renderBackend.glState.currentUnit;
dtexture currentTexture = renderBackend.glState.textureUnits[unit].currentTexture;

if(fboTexId == currentTexture) {
    return;
}

glBindTexture(GL_TEXTURE_2D, fboTexId);
renderBackend.glState.textureUnits[unit].currentTexture = fboTexId;
顶点着色器

//varying vec3 vertex_normal;
varying vec4 shadowCoord;

uniform mat4 shadowMatrix;

void main() {
    gl_FrontColor   = gl_Color;
    gl_Position     = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
    gl_TexCoord[0]  = gl_MultiTexCoord0;

    //vertex_normal = normalize(gl_NormalMatrix * gl_Normal);
    shadowCoord = shadowMatrix * (gl_ModelViewMatrix * gl_Vertex);
}
片段着色器

uniform sampler2D diffuse;
uniform sampler2D shadowMap;

//varying vec3 vertex_normal;
varying vec4 shadowCoord;

void main() {
    vec4 color = texture2D(diffuse, gl_TexCoord[0].st);

    vec4 shadowCoordinateWdivide = shadowCoord / shadowCoord.w;
    float shadow = 1.0;

    if(shadowCoordinateWdivide.x >= 0.0 && shadowCoordinateWdivide.x < 1.0 &&
       shadowCoordinateWdivide.y >= 0.0 && shadowCoordinateWdivide.y < 1.0 &&
       shadowCoordinateWdivide.z >= 0.0 && shadowCoordinateWdivide.z < 1.0) {
        // Used to lower moiré pattern and self-shadowing
        shadowCoordinateWdivide.z += 0.0005;


        float distanceFromLight = texture2D(shadowMap, shadowCoordinateWdivide.st).z;

        if(shadowCoord.w > 0.0) {
            shadow = distanceFromLight < shadowCoordinateWdivide.z ? 0.0 : 1.0;
        }
    }

    gl_FragColor = vec4((color * shadow).xyz, color.a);

}

显示您的代码可能会增加有人解决您问题的可能性。我不是那个人,多想。我希望有人能指出问题,而不必粘贴我的代码,因为它的复杂性,但我设法剥离出足够的代码粘贴在这里。显示代码,你设置你的深度纹理。例如,如果启用纹理比较,则使用sampler2D对其进行采样将产生未定义的结果,通常为黑色。添加了用于设置FBO深度的代码。我注意到,当我将FBO深度渲染为2D图像进行调试时,根据灯光投影的近平面,所有内容都是纯白色或纯灰色。深度缓冲区不是应该从黑到白从前到后逐渐衰减吗?深度缓冲区实际上存储的是在某个位置gl_FragCoord.xy通过深度测试的最后一个片段的窗口空间Z坐标gl_FragCoord.Z。使用默认深度范围,近平面生成的窗空间Z为0.0,远平面生成的窗空间Z为1.0。一种解释方法当然是强度,例如[0.0,1.0]中的灰度。顺便说一下,shadowSampler2D将产生您所建议的结果。它将深度查找与比较相结合,然后返回二进制通过/失败结果,而不是实际深度。