0

我试图弄清楚如何在延迟渲染器中渲染天空盒,以便它可以包含在后期处理效果中,但是我的几何阶段在视图空间中,不幸的是,这个阶段的天空盒将受到它相对于像任何物体一样发光(它的行为就像离光源很远的大盒子,并且显示得很暗)。我没有尝试在后期处理中加入天空盒的设置如下:

1:(绑定 FBO)将几何体渲染到颜色、法线、位置 FBO 纹理附件(取消绑定 FBO)。

2:(绑定FBO)渲染场景并计算屏幕空间的光照。(取消绑定FBO)

3:(绑定FBO)应用后期处理效果(取消绑定FBO)

4:将几何FBO的深度缓冲区blit到默认帧缓冲区

5:渲染天空盒。

我试图用 3 像这样切换第 5 步:

2:(绑定FBO)渲染场景并计算屏幕空间中的光照。

5:渲染天空盒

(解除绑定FBO)

3:(绑定FBO)应用后期处理效果(取消绑定FBO)

4:将几何FBO的深度缓冲区blit到默认帧缓冲区

但显然天空盒没有关于场景的深度信息,而是在灯光舞台上渲染。如果我尝试在 2 和 5 之间进行任何深度 blitting,我相信我正在进行无效的 GL 调用,因为我在调用时已经绑定到 FBO

 GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, DeferredFBO.fbo_handle);
 GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, 0); // Write to default
                                                            // framebuffer or a skybox framebuffer    


    GL30.glBlitFramebuffer(0, 0, DisplayManager.Width,
            DisplayManager.Height, 0, 0, DisplayManager.Width,
            DisplayManager.Height, GL11.GL_DEPTH_BUFFER_BIT,
            GL11.GL_NEAREST);
4

2 回答 2

2

所以我想出了一个非常简单的hacky解决方案来解决这个问题,而无需合并任何纹理障碍或弄乱深度或颜色缓冲区。

我实际上是在延迟渲染过程的几何过程中渲染天空盒几何,我渲染天空盒并在片段着色器中设置一个标志来为我的天空盒着色,记住修改视图矩阵以使用顶点中的另一个统一标志移除平移着色器。在片段着色器中,我将天空盒颜色设置为这样。这是一个基本的总结,没有粘贴所有的代码。

layout (binding = 4) uniform samplerCube cubeMap;
uniform float SkyRender;
void main(){
if(SkyRender){
vec4 SkyColor = texture(cubeMap, skyTexCoords);
gAlbedoSpec.rgb = SkyColor.rgb;
gAlbedoSpec.a = -1;
}else{
gAlbedoSpec.rgb = texture(DiffuseTexture, TexCoords);
gAlbedoSpec.a =   texture(SpecularTexture, TexCoords).r;
}

我在颜色缓冲区中将天空盒的 alpha 分量设置为我的 Lighting pass 的标志。在这里,我将其设置为-1。

在我的光照通道中,如果我的 gAlbedoSpec alpha 值为 -1,我只需选择使用 Diffuse Only 为我的盒子着色,而不是添加光照计算。

if(Diffuse.a > -1){
FragColor = SphereNormal * vec4(Dlighting, 1.0)+vec4(Slighting, 1.0);
}else{
FragColor = Diffuse ;
}

它相当简单,不需要太多代码即可完成工作。

于 2016-01-04T09:42:13.243 回答
1

然后给它它缺乏的深度信息。

在步骤 1 中渲染场景时,您使用了深度缓冲区。因此,当您绘制天空盒时,您需要一个使用相同深度缓冲区的 FBO。但是这个 FBO 还需要使用您在步骤 2 中渲染的彩色图像。

现在,此 FBO不能与您在步骤 2 中使用的 FBO 相同。为什么?

因为那将是未定义的行为。据推测,第 2 步从您的深度缓冲区读取以重建位置(如果不是这种情况,那么您可以从第 2 步将深度缓冲区附加到 FBO。但话又说回来,您也浪费了大量的性能)。但是该深度缓冲区也附加到 FBO。这使它成为未定义的行为。即使您没有写入深度,它在 OpenGL 下仍然是未定义的。

因此,您将需要另一个 FBO,它具有来自步骤 1 的深度缓冲区和来自步骤 2 的颜色缓冲区。

除非您有权访问OpenGL 4.5/ARB_texture_barrier/NV_texture_barrier。使用该功能,如果您使用写入掩码关闭对深度缓冲区的写入,它就会成为定义的行为。您需要做的就是glTextureBarrier在执行第 2 步之前发出 a。因此,如果您有另一个 FBO,则不需要。

无论哪种情况,在渲染天空盒时保持启用深度测试,但关闭深度写入。这将允许剔除现实世界后面的片段,但天空盒片段的深度将无限远。

于 2015-12-19T23:19:25.110 回答