You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL深度纹理与阴影立方体贴图渲染全白问题求助

OpenGL深度纹理全白问题排查与解决

问题现象

将深度纹理绘制到正方形上时显示全白,生成点光源阴影立方体贴图时也出现同样情况。

核心问题与解决方案

1. 模型顶点未正确转换到光源裁剪空间

问题原因

生成阴影贴图的顶点着色器仅使用shadowTransform(投影×视图矩阵),但未结合模型的model矩阵,导致物体局部空间顶点未转换到世界空间,无法落入光源的视锥体范围内,所有片段深度值被设为远平面的1.0,采样后显示全白。

解决方案

  • 修改阴影贴图顶点着色器,增加model矩阵uniform,完整计算MVP:
const char* pshadowVertexShader = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"uniform mat4 shadowTransform; // 投影×光源视图矩阵\n"
"uniform mat4 model; // 模型矩阵\n"
"void main()\n"
"{\n"
"   gl_Position = shadowTransform * model * vec4(aPos, 1.0f);\n"
"}\0";
  • 在model->draw()方法中,将当前模型的model矩阵传入着色器的model uniform。

2. 着色器编译/链接错误未检测

问题原因

renderInit函数未检查着色器编译和程序链接状态,可能存在语法错误导致着色器未正常工作,深度缓冲未被正确写入。

解决方案

修改renderInit函数,添加错误检查:

unsigned int renderInit(std::vector<const char*>& shaderCodeQ){
    unsigned int shaderProgram;
    unsigned int vertexShader, fragmentShader;
    int success;
    char infoLog[512];

    // 编译顶点着色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &shaderCodeQ[0], NULL);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if(!success) {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "顶点着色器编译错误:\n" << infoLog << std::endl;
    }

    // 编译片段着色器
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &shaderCodeQ[1], NULL);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if(!success) {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "片段着色器编译错误:\n" << infoLog << std::endl;
    }

    // 链接程序
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    if (shaderCodeQ.size() > 2) {
        unsigned int geometryShader = glCreateShader(GL_GEOMETRY_SHADER);
        glShaderSource(geometryShader, 1, &shaderCodeQ[2], NULL);
        glCompileShader(geometryShader);
        glGetShaderiv(geometryShader, GL_COMPILE_STATUS, &success);
        if(!success) {
            glGetShaderInfoLog(geometryShader, 512, NULL, infoLog);
            std::cout << "几何着色器编译错误:\n" << infoLog << std::endl;
        }
        glAttachShader(shaderProgram, geometryShader);
    }
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if(!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "着色器程序链接错误:\n" << infoLog << std::endl;
    }

    // 删除中间着色器
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    if(shaderCodeQ.size()>2) glDeleteShader(glCreateShader(GL_GEOMETRY_SHADER));

    return shaderProgram;
}

3. 深度纹理参数与采样优化

问题原因

  • 深度纹理使用GL_REPEAT环绕模式,边缘采样可能引入异常值;
  • 直接采样深度值(范围0~1)时,近平面深度接近0(黑色),远平面接近1(白色),若所有片段都在远平面则显示全白。

解决方案

  • 调整深度纹理的环绕模式为GL_CLAMP_TO_EDGE:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  • 修改显示用片段着色器,对深度值做线性缩放,便于观察差异:
const char* pFragShadowTest = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec2 TexCoord;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
"   // 缩放深度值,让差异更明显\n"
"   float depth = texture(ourTexture, TexCoord).r * 0.1;\n"
"   FragColor = vec4(vec3(depth),1.0f);\n"
"}\n\0";

4. 确认物体在光源视锥体内

问题原因

正交投影矩阵glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 0.1f, 30.0f)的范围可能未覆盖所有物体,导致物体被完全裁剪,深度缓冲无有效数据。

解决方案

  • 扩大正交投影的范围,例如调整为glm::ortho(-20.0f, 20.0f, -20.0f, 20.0f, 0.1f, 50.0f);
  • 验证viewPos(光源位置)和lookAt目标点是否正确,确保光源能看到所有物体。

额外优化建议

  • 在阴影贴图的片段着色器中显式写入深度值(可选,但更稳妥):
const char* pshadowFragShader = "#version 330 core\n"
"void main()\n"
"{\n"
"   gl_FragDepth = gl_FragCoord.z;\n"
"}\0";
  • 绘制阴影贴图前,确保启用GL_DEPTH_TEST并正确清除深度缓冲(当前代码已包含,但需确认)。

内容的提问来源于stack exchange,提问作者minisparks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 00:01:38