OpenGL阴影映射,具有多个glDrawElements的帧缓冲区

Posted

技术标签:

【中文标题】OpenGL阴影映射,具有多个glDrawElements的帧缓冲区【英文标题】:OpenGL shadow mapping, frame buffer with multiple glDrawElements 【发布时间】:2014-04-27 02:35:45 【问题描述】:

我有一个由很多对象组成的场景,当我渲染它们时,我会遍历场景中的所有项目并在它们上调用 glDrawElements。这工作正常。但是,现在我正在实现场景的阴影映射,并且使用相同的方式绘制到阴影缓冲区。但是,只有场景中的第一个元素以正确的方式绘制到纹理,我通过将深度纹理附加到场景元素来检查这一点,您将在下面看到。

代码如下:

glBindFramebuffer(GL_FRAMEBUFFER, vFrameBuffers[ShadowFB]);
glViewport(0,0,1024,1024);

glClearDepth(1.0f);
glClear(GL_DEPTH_BUFFER_BIT);

glUseProgram(shadowShader);
depth_loc = glGetUniformLocation(shadowShader, "depthProj");
model_view_loc = glGetUniformLocation(shadowShader, "modelmat");

glUniformMatrix4fv(depth_loc, 1, GL_FALSE, depthproj);

depthproj = mat4(1.0);
depthproj = Ortho(-250.0f, 250.0f, -200.0f, 200.0f, -200.0f, 200.0f);
depthproj = depthproj * RotateX(15);
depthproj = depthproj * RotateY(220);

for (int i = 0; i < _objectArray.size(); i++)

    modelmat = mat4(1.0);
    modelmat = modelmat*Translate(_objectArray[i]->getLocation()->getX(),
        _objectArray[i]->getLocation()->getY(),
        _objectArray[i]->getLocation()->getZ());

    glUniformMatrix4fv(model_view_loc, 1, GL_FALSE, modelmat);

    if (_objectArray[i]->getType() == TypeMountain)
    
        glBindVertexArray(vArrays[ShadowMountainA]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowMountainE]);
        glDrawElements(GL_TRIANGLES, 40*40*6, GL_UNSIGNED_SHORT, NULL);
        glBindVertexArray(0);
    
    else if (_objectArray[i]->getType() == TypePasture)
       
        glBindVertexArray(vArrays[ShadowPastureA]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowPastureE]);
        glDrawElements(GL_TRIANGLES, 40*40*6, GL_UNSIGNED_SHORT, NULL);
        glBindVertexArray(0);
    
    else if (_objectArray[i]->getType() == TypeWater)
       
        glBindVertexArray(vArrays[ShadowWaterA]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowWaterE]);
        glDrawElements(GL_TRIANGLES, 40*40*6, GL_UNSIGNED_SHORT, NULL);
        glBindVertexArray(0);
    
    else if (_objectArray[i]->getType() == TypeTree)
       
        glBindVertexArray(vArrays[ShadowTreeA]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowTreeE]);
        glDrawElements(GL_TRIANGLES, 180, GL_UNSIGNED_SHORT, NULL);
        glBindVertexArray(0);
    


glUseProgram(0);

当我只在山对象上运行它时,这是我得到的结果图像,你可以看到它是正确的。 它也单独适用于其他场景元素。 我的问题是如何使用多次绘制在同一个缓冲区中毫无问题地绘制?

编辑: 仅仅因为这里请求了阴影着色器组件:

顶点着色器:

#version 330 core

uniform mat4 depthProj;
uniform mat4 modelmat;

layout(location = 0) attribute vec4 vPosition;

void main()

    gl_Position = depthProj * modelmat * vPosition;

片段着色器:

#version 330 core

layout(location = 0) out float fragmentDepth;

void main()


【问题讨论】:

“我正在通过将深度纹理附加到您将在下面看到的场景元素来检查这一点” 这看起来不像我见过的任何深度纹理。为什么是彩色的?也许您应该包含用于生成该图像的着色器以显示实际情况。 它不是彩色的,深度纹理用于围绕山的小岛。它们是白色的,除了山的深度值是灰色的,可以在纹理的中心看到。阴影着色器没有任何价值。 您不会在尝试对其进行采样的同时绘制深度纹理,是吗?这可以解释为什么除了你的山之外,每种类型的物体都有这种行为。 深度纹理仅在实际渲染过程中使用,即在我上面放置的循环之后。这与上面的循环非常相似,但带有实际的着色器及其变量。如果 OpenGL 在 glDrawElements 之间访问它,我不知道。 【参考方案1】:

我不知道为什么,但是当台词出现时,

glUniformMatrix4fv(depth_loc, 1, GL_FALSE, depthproj);

glUniformMatrix4fv(model_view_loc, 1, GL_FALSE, modelmat);

变成了;

glUniformMatrix4fv(depth_loc, 1, GL_TRUE, depthproj);

glUniformMatrix4fv(model_view_loc, 1, GL_TRUE, modelmat);

场景按原样绘制。

【讨论】:

我只是想在问题下发表相关评论。在原始代码中,您在构建矩阵之前为depthproj 设置了统一。无论如何,如果您需要 GL_TRUE 来表示该参数,这意味着您正在以行优先顺序构建矩阵,而 OpenGL 需要列优先矩阵。

以上是关于OpenGL阴影映射,具有多个glDrawElements的帧缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

带有立方体贴图的 OpenGL 点光阴影映射

OpenGL阴影映射几乎可以工作

Android NDK SDL2 OpenGL ES 2 阴影映射(定向)- 可能吗?

OpenGL 3.3 两个 GPU 上的两个不同结果 nVidia Optimus 与阴影映射

使用立方体贴图(OpenGL/GLSL)的点光源是不是可以实现软阴影?

OpenGL 纹理映射禁用着色