OpenGL implementing skybox in a deferred renderer - opengl

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

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.

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.

Related

libgdx heighmap shader distortion artefact

Currently making a game and I want to add nice shader effect like water distortion.
I am rendering the scene to a FBO then apply a heightmap distortion shader on it.
The distortion is applied by the fragment shader.
normalMapPosition is the color vector at the current position of the normal map.
vec2 normalCoord = v_texCoord0;
vec4 normalMapPosition = 2 * texture2D(u_normals, v_texCoord0);
vec2 distortedCoord = normalCoord + (normalMapPosition.xz * 0.05);
then render it to the screen and I obtain the following result
The problem is that there is a diagonal artefact traversing the whole image.
I think this is due to the treatment by openGL of the texture as two triangles.
Is there a nice way to handle this kind of issue?
I finaly found the solution, the problem came from the utilisation of the same FBO to draw the scene and then to render the shader like:
batch.setShader(waterfallShaderProgram)
fbo.begin();
batch.begin();
// here is the problem, fbo is started and used to
// draw at the same time
batch.draw(fbo.getColorBufferTexture());
batch.end()
fbo.end();
the scene is rendered to the FBO fbo in order to apply other effect on top.
Introducing a new FBO fbo2 solved the issue.
batch.setShader(waterfallShaderProgram)
fbo2.begin();
batch.begin();
batch.draw(fbo.getColorBufferTexture());
batch.end()
fbo2.end();

OpenGL - How to access depth buffer values? - Or: gl_FragCoord.z vs. Rendering depth to texture

I want to access the depth buffer value at the currently processed pixel in a pixel shader.
How can we achieve this goal? Basically, there seems to be two options:
Render depth to texture. How can we do this and what is the tradeoff?
Use the value provided by gl_FragCoord.z - But: Is this the correct value?
On question 1: You can't directly read from the depth buffer in the fragment shader (unless there are recent extensions I'm not familiar with). You need to render to a Frame Buffer Object (FBO). Typical steps:
Create and bind an FBO. Look up calls like glGenFramebuffers and glBindFramebuffer if you have not used FBOs before.
Create a texture or renderbuffer to be used as your color buffer, and attach it to the GL_COLOR_ATTACHMENT0 attachment point of your FBO with glFramebufferTexture2D or glFramebufferRenderbuffer. If you only care about the depth from this rendering pass, you can skip this and render without a color buffer.
Create a depth texture, and attach it to the GL_DEPTH_ATTACHMENT attachment point of the FBO.
Do your rendering that creates the depth you want to use.
Use glBindFramebuffer to switch back to the default framebuffer.
Bind your depth texture to a sampler used by your fragment shader.
Your fragment shader can now sample from the depth texture.
On question 2: gl_FragCoord.z is the depth value of the fragment that your shader is operating on, not the current value of the depth buffer at the fragment position.
gl_FragCoord.z is the window-space depth value of the current fragment. It has nothing to do with the value stored in the depth buffer. The value may later be written to the depth buffer, if the fragment is not discarded and it passes a stencil/depth test.
Technically there are some hardware optimizations that will write/test the depth early, but for all intents and purposes gl_FragCoord.z is not the value stored in the depth buffer.
Unless you render in multiple passes, you cannot read and write to the depth buffer in a fragment shader. That is to say, you cannot use a depth texture to read the depth and then turn around and write a new depth. This is akin to trying to implement blending in the fragment shader, unless you do something exotic with DX11 class hardware and image load/store, it just is not going to work.
If you only need the depth of the final drawn scene for something like shadow mapping, then you can do a depth-only pre-pass to fill the depth buffer. In the second pass, you would read the depth buffer but not write to it.

Access depth-stencil texture in a shader program

It seems to be difficult to find information about how to access depth and stencil buffers in shaders of successive render passes.
In a first render pass, I do not only render color and depth information but also make use of stencil operations to count objects. I use a multi render target FBO for this, with color buffers and a combined depth stencil buffer attached. All of them are in the form of textures (no render buffer objects involved).
In a second render pass (when rendering to the screen), I want to access the previously computed stencil index on a per-pixel basis (but not necessarily the same pixel I'm drawing then), similar like you would like to access the previously rendered color buffer to apply some post processing effect.
But I fail to bind the depth stencil texture in the second pass to my shader program as a uniform. At least only black values are read from it, so I guess it's not bound correctly.
Is it possible to bind a depth stencil texture to a texture unit for use in a shader program? Is it impossible to access depth and stencil textures using "normal" samplers? Is it possible with some "special" sampler? Does it depend on the interpolation mode set on the texture or a similar setting?
If not, what is the best (fastest) way to copy the stencil information into a separate color texture between these two render passes? Maybe involving a third render pass which draws a single color using stencil test (I only need a binary version of the stencil buffer in the final render pass, to be precise I need to test if the value is zero).
The setup for the textures being used by the intermediate FBO is as follows:
// The textures for color information (GL_COLOR_ATTACHMENT*):
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// The texture for depth and stencil information (GL_DEPTH_STENCIL_ATTACHMENT*):
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
In the second render pass, I currently only try to "debug" the contents of all textures. Therefore I setup the shader with these values:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, <texture>);
glUniform1i(texLocation, 0);
and let the shader program simply copy the texture to the screen:
uniform sampler2D tex;
in vec2 texCoord;
out vec4 fragColor;
void main() {
fragColor = texture2D(tex, texCoord);
}
The results are as followed:
When <texture> above refers to one of my color textures, I see the color output rendered in the first render pass, which is what I expect.
When <texture> above refers to the depth stencil texture, the shader doesn't do anything (I see the color with which I clear the screen).
When copying the depth stencil texture to the CPU and examine it, I see both the depth and stencil information in the packed 24 + 8 bit data as expected.
I have no experience with using stencil as a texture, but you may want to take a look at the following extension :
http://www.opengl.org/registry/specs/ARB/stencil_texturing.txt
Another option could be to create a view of the texture using
http://www.opengl.org/registry/specs/ARB/texture_view.txt
Or you could count objects without the stencil buffer, perhaps using MRT and additive blending on second render target using :
http://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
But I'm afraid those options are not included in pure GL3.3...

How to draw from the inside of the light geometry in deferred shading

I'm trying to implement a deferred shader with OpenGL and GLSL and I'm having trouble with the light geometry. These are the steps I'm taking:
Bind multitarget framebuffer
Render color, position, normal and depth
Unbind framebuffer
Enable blend
Disable depth testing
Render every light
Enable depth testing
Disable blend
Render to screen
But since I'm only rendering the front face, when I'm inside a light it disappears completely, rendering the back face does not work, since I would get double the light power (And when inside, half [or the normal amount]).
How can I render the same light value from inside and outside the light geometry?
well in my case, i do it like that:
Bind gbuffer framebuffer
Render color, position, normal
Unbind framebuffer
Enable blend
Enable depth testing
glDepthMask(0);
glCullFace(GL_FRONT); //to render only backfaces
glDepthFunc(GL_GEQUAL); //to test if light fragment is "behind geometry", or it shouldn't affect it
Bind light framebuffer
Blit depth from gbuffer to light framebuffer //so you can depth-test light volumes against geometry
Render every light
If i remember correctly, in my deferred renderer i just render only the backfaces of the light volume. The drawback is you cannot depth test, you will only know if a light is behind a geometry after the light calculation is done and discard the pixel.
As another answer explained, you can do depth testing. Test for greater or equal to see if the backface is behind or on a geometry, therefore intersects with the surface of the geometry.
Alternatively you could check if you are inside the light volume when rendering and switch front faces accordingly.

how to handle depth in glsl

I have a problem with FBO and depth in openGL. I am passing projection, view and model matrices to a shader that writes to the g buffer. When I unbind the FBO and write to gl_FragColor the scene displays as it ought. But when I write to gl_FragData[0] then write the accompanying texture to a screen aligned quad, objects are drawn according to inverse order processed rather than depth... I can see through objects processed first to objects processed after. Has anyone had the same problem and do they know a fix? Or could someone provide syntax on reading depth values from the vertex shader, querying the current depth, then writing to the depth buffer depending on a comparison, ie, handling the operation manually in the fragment shader.
Your main frame-buffer most likely has the depth, while your manually created FBO might not have it. Therefore, when drawing to the screen you have depth-sorted geometry, while your FBO can not provide that and internally works with disabled depth testing having no storage associated with it.