问题描述:

I am trying to figure out how to render a skybox in a deferred renderer so that it can be included in post processing effects, However my Geometry stage is in view space and unfortunately the skybox in this stage will be effected by it's position relative to the light as any object would (it behaves like large box located very far from the light source and shows up very dark).

my setup without trying to incorporate the skybox in post processing is as follows:

1:(bind FBO) Render Geometry to color, normal, position FBO texture attachments (unbind FBO).

2:(bind FBO) Render the scene and calculate lighting in screen space.(unbind FBO)

3:(bind FBO) apply post processing effects (unbind FBO)

4: blit the Geometry FBO's depth buffer to the default frame buffer

5: render skybox.

I've tried to switch step 5 with 3

like this:

2:(bind FBO) Render the scene and calculate lighting in screen space.

5: render skybox

(unbind FBO)

3:(bind FBO) apply post processing effects (unbind FBO)

4: blit the Geometry FBO's depth buffer to the default frame buffer

but obviously the skybox has no depth information about the scene and renders on top of the lighting stage. And if I try to do any depth blitting between 2 and 5, I believe I am making invalid GL calls because I'm already bound to an FBO while calling

 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);

网友答案:

Then give it the depth information it lacks.

When you rendered your scene in step 1, you used a depth buffer. So when you draw your skybox, you need an FBO that uses that same depth buffer. But this FBO also needs to use the color image that you rendered to in step 2.

Now, this FBO cannot be the same FBO you used in step 2. Why?

Because that would be undefined behavior. Presumably, step 2 reads from your depth buffer to reconstruct the position (if this is not the case, then you can just attach the depth buffer to the FBO from step 2. But then again, you're also wasting tons of performance). But that depth buffer is also attached to the FBO. And that makes it undefined behavior. Even if you're not writing to the depth, it is still undefined under OpenGL.

So you will need another FBO, which has the depth buffer from step 1 with the color buffer from step 2.

Unless you have access to OpenGL 4.5/ARB_texture_barrier/NV_texture_barrier. With that feature, it becomes defined behavior if you use write masks to turn off writes to the depth buffer. All you need to do is issue a glTextureBarrier before performing step 2. So you don't need another FBO if you have that.

In either case, keep the depth test enabled when rendering your skybox, but turn off depth writing. This will allow fragments behind your actual world to be culled, but the depth of the skybox fragments will be infinitely far away.

网友答案:

So I came up with a really easy hacky solution to this problem without having to incorporate any texture barriers or messing with the depth or color buffers.

I actually render the Skybox Geometry in the Geometry pass of the Deferred Rendering process, I render the skybox and set a flag in the fragment shader to color my skybox, remembering to modify the view matrix to remove the translation with another uniform flag in the vertex Shader. In the fragment shader I set the skybox color as such. Here is a basic summary without pasting all of the code.

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;
}

I set the alpha component of my skybox in the Color buffer as a flag for my Lighting pass. Here I set it to to -1.

In my lighting pass I simply choose to color my box with Diffuse Only instead of adding lighting calculations if my gAlbedoSpec alpha value is -1.

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

It's fairly simple and doesn't require much code and gets the job done.

相关阅读:
Top