OpenGL在延迟渲染器中实现skybox

时间:2015-12-19 22:46:16

标签: opengl deferred-rendering

我试图找出如何在延迟渲染器中渲染天空盒,以便它可以包含在后期处理效果中。但是我的几何阶段在视图空间中,不幸的是,此阶段的天空盒将受其影响&# 39;相对于光的位置,就像任何物体一样(它的行为就像位于离光源很远的大盒子,显得很暗)。 我的设置没有尝试在后期处理中加入天空盒如下:

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

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

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

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

5:渲染天空盒。

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

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

5:渲染天空盒

(取消绑定FBO)

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

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

但很明显,天空盒没有关于场景的深度信息,而是在灯光舞台上呈现。如果我尝试在2到5之间进行任何深度调整,我相信我正在进行无效的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);

2 个答案:

答案 0 :(得分:1)

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

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

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

因为那是undefined behavior。据推测,步骤2从深度缓冲区读取以重建位置(如果不是这种情况,那么您可以将深度缓冲区附加到步骤2中的FBO。但是再次,您也浪费吨< / em>表现)。但是这个深度缓冲区也附加在FBO上。这使得它成为未定义的行为。即使你没有写入深度,在OpenGL下它仍然是未定义的。

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

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

在任何一种情况下,在渲染天空盒时都要启用深度测试,但turn off depth writing。这将允许剔除现实世界背后的碎片,但天空盒碎片的深度将无限远。

答案 1 :(得分:1)

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

我实际上在Deferred Rendering过程的Geometry传递中渲染Skybox Geometry,我渲染天空盒并在片段着色器中设置一个标志来为我的天空盒着色,记住修改视图矩阵以使用另一个统一标志移除翻译在顶点着色器中。在片段着色器中,我设置了天空盒颜色。这是一个基本的摘要,没有粘贴所有代码。

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分量设置在Color缓冲区中,作为我的Lighting pass的标志。在这里,我将其设置为-1。

在我的灯光通道中,我只选择使用“仅漫反射”为我的方框着色,而不是在我的gAlbedoSpec alpha值为-1时添加光照计算。

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

这很简单,不需要太多代码就可以完成工作。