0

So as a final step in my deferred shader I've been trying to get a skybox to work. Essentially I go through all the regular deferred shader steps and then use some post processing stuff like HDR and bloom, this final step is rendered to a full screen quad using a forward shader. Now if I just render the skybox separately or the deferred shading results everything looks fine and normal. It's when I try to render the skybox last that it doesn't end up on the screen.

So basically after I render the quad with the results I want to render the skybox using the depth values from the geometry pass. I've tried blitting the depth buffer as Deferred Rendering Skybox OpenGL suggests but it doesn't have any effect and I think the issue is with how I set up my depth buffer for the FBO since it shares a stencil attachment.

My render call for the skybox:

//draw skybox
glEnable(GL_DEPTH_TEST);

glBindFramebuffer(GL_READ_FRAMEBUFFER, mFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, mWindowWidth, mWindowHeight, 0, 0, mWindowWidth, mWindowHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// Draw skybox as last
glDepthFunc(GL_LEQUAL);  // Change depth function so depth test passes when values are equal to depth buffer's content
ShaderMan.bindShader(SKY_BOX_SHADER);
glm::mat4 view = glm::mat4(glm::mat3(CameraMan.getActiveCamera()->getViewMatrix()));    // Remove any translation component of the view matrix
glm::mat4 projection = CameraMan.getActiveCamera()->getProjectionMatrix();
glUniformMatrix4fv(ShaderMan.getActiveShader().getUniformLocation("viewMatrix"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(ShaderMan.getActiveShader().getUniformLocation("projectionMatrix"), 1, GL_FALSE, glm::value_ptr(projection));
// skybox cube
glUniform1i(ShaderMan.getActiveShader().getUniformLocation("skybox"), 0);
mSkybox.render();
glDepthFunc(GL_LESS); // Set depth function back to default
ShaderMan.unbindShader();

and how I set up the deferred FBO

//POSIITON
glGenTextures(1, &mPositionTexture);
glBindTexture(GL_TEXTURE_2D, mPositionTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, mWindowWidth, mWindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
//Nearest min mag filters since we dont want interpolated values
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glFrameBuffer attaches a texture as a color attachment, depth attachment or stencil etc
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mPositionTexture, 0);

glGenTextures(1, &mNormalTexture);
glBindTexture(GL_TEXTURE_2D, mNormalTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, mWindowWidth, mWindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mNormalTexture, 0);

//Combined color and specular buffer
glGenTextures(1, &mSpecularAlbedoTexture);
glBindTexture(GL_TEXTURE_2D, mSpecularAlbedoTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, mWindowWidth, mWindowHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, mSpecularAlbedoTexture, 0);

//Depth & stencil texture for the FBO
glGenTextures(1, &mDepthTexture);
glBindTexture(GL_TEXTURE_2D, mDepthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, mWindowWidth, mWindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, mDepthTexture, 0);

// final
glGenTextures(1, &mFinalTexture);
glBindTexture(GL_TEXTURE_2D, mFinalTexture);
///Used to be GL_RGBA only
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, mWindowWidth, mWindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, mFinalTexture, 0);

I'm thinking the GL_DEPTH_STENCIL_ATTACHMENT is what messes something up, but I also can't see why you shouldnt be able to blit the depth attachment if you specify it in the blit function

An image of the result, no skybox: result

EDIT

I tried searching around a bit and changed the format to GL_DEPTH_24_STENCIL8 in case the main fbo had a different float format, but that did not help either.

Community
  • 1
  • 1
Johan
  • 121
  • 1
  • 11

1 Answers1

0

You shouldn't attempt to blit an FBO depth buffer to the default depth buffer. To blit from one depth buffer to another the internal formats of both must be exactly the same. Whilst you can define the format of an FBO, the default depth buffer is implementation defined. You might be able to deduce its format by trial and error but the solution will not be portable.

One solution would be to write out your depths to an R32F texture colour attachment during the geometry pass. Later when you're drawing your skybox to the default framebuffer you can bind the R32F texture to a sampler and read the depth for that pixel in the fragment shader. Only output the skybox to fragments where the depth is 0.0f.

Fibbs
  • 1,350
  • 1
  • 13
  • 23
  • It seems that this is the case, as GL_INVALID_OPERATION gets thrown and one of the reasons is " GL_INVALID_OPERATION is generated if mask contains GL_DEPTH_BUFFER_BIT or GL_DEPTH_BUFFER_BIT and the source and destination depth and stencil formats do not match." which is a bit strange since a lot of tutorials like http://learnopengl.com/#!Advanced-Lighting/Deferred-Shading uses it with no issues. I guess I'll have to add another color texture and store the depth then. I'll implement it and see how it goes, thanks for the help! – Johan Oct 19 '15 at 20:54
  • For future references, I'm using glfw and tried setting glfwWindowHint(GLFW_DEPTH_BITS, 24); and glfwWindowHint(GLFW_STENCIL_BITS, 8); as well as setting GL_DEPTH24_STENCIL8 which did nothing to help the issue. – Johan Oct 19 '15 at 21:20
  • As I said, the default depth buffer is implementation defined. This means it may be possible to guess the internal format on _your_ _system_ but there's no guarantee this will work on anybody elses. It's not all gloom and doom. You can actually use the depth stored in the R32F texture to calculate world position which would allow you to get rid of your position texture and save memory/bandwidth. That's a topic for a different question though. – Fibbs Oct 19 '15 at 21:34