If I understand correctly, you can attach textures to an FBO and then use glDrawBuffers to link those attachment points to (fragment) shader output indices. Where is this latter state stored after a glDrawBuffers call? The currently bound shader, FBO, or is it a global OpenGL state?
glDrawBuffer(s) sets framebuffer object state.
Related
I have rendered a texture to an FBO in the hope that I can now apply effects to that texture before displaying it. I cant work out how to access the FBO array to change it. Any idea? Thanks for your time
Could you specify what you mean by adding effects? The basic idea of a fbo is to render everything to that fbo and then apply that fbo to a texture. If you wish to know how to bind that framebuffer to a texture, simple create and setup a texture with an empty data set for glTexImage2D. Then, call glFramebufferTexture2D with your framebuffer object bound and pass in your texture as one of the arguments. To render to your framebuffer, call glBindFramebuffer. To bind your framebuffer texture, simply call glBindTexture, like any other 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.
I would like to know if GL_TEXTURE_2D is active in the shader.
I am binding a color to the shader as well as the active texture (if GL_TEXTURE_2D is set) and need to combine these two.
So if texture is bound, mix the color and the texture (sampler2D * color) and if no texture is bound, use color.
Or should I go another way about this?
It is not quite clear what you mean by 'GL_TEXTURE_2D is active' or 'GL_TEXTURE_2D is set'.
Please note the following:
glEnable(GL_TEXTURE_2D) has no effect on your (fragment) shader. It parametrizes the fixed function part of your pipeline that you just replaced by using a fragment shader.
There is no 'direct'/'clean' way of telling from inside the GLSL shader whether there is a valid texture bound to the texture unit associated with your texture sampler (to my knowledge).
Starting with GLSL 1.3 you might have luck using textureSize(sampler, 0).x > 0 to detect the presence of a valid texture associated with sampler, but that might result in undefined behavior.
The ARB_texture_query_levels extension does indeed explicitly state that textureQueryLevels(gsampler2D sampler) returns 0 if there is no texture associated with sampler.
Should you go another way about this? I think so: Instead of making a decision inside the shader, simply bind a 1x1 pixel texture of 'white' and unconditionally sample that texture and multiply the result with color, which will obviously return 1.0 * color. That is going to be more portable and faster, too.
In DirectX you are able to have separate render targets and depth buffers, so you can bind a render target and a depth buffer, do some rendering, remove the depth buffer and then do more rendering using the old depth buffer as a texture.
How would you go about this in opengl? From my understanding, you have a framebuffer object that contains both the color buffer(s) and an optional depth buffer. I don't think I can bind several framebuffer objects at the same time, would I have to recreate the framebuffer object every time it changes(probably several times a frame)? How do normal opengl programs do this?
A Framebuffer Object is nothing more than a series of references to images. These can be images in Textures (such as a mipmap layer of a 2D texture) or Renderbuffers (which can't be used as textures).
There is nothing stopping you from assembling an FBO that uses a texture's image for its color buffer and a texture's image for its depth buffer. Nor is there anything stopping you from later (so long as you're not rendering to that FBO while doing this) sampling from the texture as a depth texture. The FBO does not suddenly own these images exclusively or something.
In all likelihood, what has happened is that you've misunderstood the difference between an FBO and OpenGL's Default Framebuffer. The default framebuffer (ie: the window) is unchangeable. You can't take it's depth buffer and use it as a texture or something. What you do with an FBO is your own business, but OpenGL won't let you play with its default framebuffer in the same way.
You can bind multiple render targets to a single FBO, which should to the trick. Also since OpenGL is a state machine you can change the binding and number of targets anytime it is required.
I am working on openGL ES2.0 and glsl and I have a question about FBO.
I pass two textures on my openGL ES2.0 code and through glsl shader, particularly fragment shader, I subtract two textures and make a binary image, just like opencv treshold function. My question is that I am not sure if I should use Renderbuffer or texture object for my FBO. I have to choose one since I can only use 1 color attachment (due to restriction of openGL ES2.0). Since the output image after my fragment shader will be a binary image (black or white), shouldn't it be Renderbuffer object?
A texture is a series of images which can be read from (via normal texturing means) and rendered into via FBOs. A renderbuffer is an image that can only be rendered into.
You should use a renderbuffer for images that you will only use as a render target. If you need to sample from it later, you should use a texture.