Creating frame buffer object with no color attachment - opengl

I know that we can create such a FBO (no color attachment, just a depth attachment) e.g this can be used for shadow mapping.
Also, the FBO completeness check states that
Each draw buffers must either specify color attachment points that
have images attached or must be GL_NONE​.
(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER​ when false). Note that this
test is not performed if OpenGL 4.2 or ARB_ES2_compatibility is
available.
My question is, is it necessary to explicitly mention this by using
glDrawBuffer(GL_NONE);
If I dont specify any color attachments, is it not understood by OpenGL that it will not have any color buffers attached?
(My Program just worked fine on OpenGL 4.0 without mentioning "glDrawBuffer(GL_NONE);" so I assume its okay not to, but wiki says FB completeness check must have failed)

In my application, using a depth buffer for shadow mapping, NOT calling
glDrawBuffer(GL_NONE);
does NOT result in an incomplete framebuffer if this framebuffer has no color attachments.
However, everything does turn into crap and the depth texture is apparently either not writeable or readable or both.
Why this is so, and whether this is universally so I will leave in the middle. I am just informing you of my findings, and my findings indicate you should be cautious with omitting this statement.

Related

Why doesn't binding to the default texture with GL_REPLACE actually replace the color drawn?

When GL_TEXTURE_ENV_MODE is set to GL_REPLACE, drawing a vertex will use the color of the current texture coordinate in the currently bound texture.
I found out that binding to the default texture with glBindTexture(GL_TEXTURE_2D, 0) has the same effect as calling glDisable(GL_TEXTURE_2D).
However a Stackoverflow answer here quotes the OpenGL spec that "(3.9.2.Texture Access) sampling from an incomplete texture will return (0,0,0,1)", where the default texture is initially an incomplete texture.
So I think I should always get black objects drawn in the given case, but in practice it behaves as if texturing is disabled.
Why doesn't binding to the default texture with GL_REPLACE actually replace the color drawn?
First of all, the "default texture object" only exists in compatibility profile (or legacy GL contexts < 3.2).
It now depends whether you sample from a texture in a shader or use the legacy fixed function pipeline. And since you care about the texuture environment, it means you are using the fixed function pipeline. And for that, you'll have to look up the compatibility profile specification too. The GL 4.6 compatibility profile spec clearly states in section 8.17.2 "Effects of Completeness on Texture Application":
For fixed-function texture access, if texturing is enabled for a
texture unit at the time a primitive is rasterized, and if the texture
image bound to the enabled texture target is not complete, then it is
as if texture mapping were disabled for that texture unit.
This behavior has been that way since the very beginning of OpenGL, and it can't be changed in compatibility profiles as existing applications may depend on it. However, using the fixed function pipeline in 2022 is something you should do only with a very good reason.

Can we sample texture attached to inactive FBO slot?

Can I attach two textures to one FBO, and switch between them using glDrawBuffers, binding the inactive one as shader input? This seems much more efficient than switching FBOs for multipass effects.
If we're assuming you don't have access to OpenGL 4.5/ARB/NV_texture_barrier, no you cannot. The part of the OpenGL specification that forbids feedback loops on framebuffer attached images does not care whether the image can be written to or not. This is also true for array layers or mipmap levels; reading from one layer while writing to another layer will not save you.
All that matters is attachment. You must either bind a new FBO that doesn't have the texture attached, or remove the attachment from the current FBO.
Though again, texture barrier functionality makes everything I said irrelevant. And considering how widespread it is, it's really not something you should be concerned about.

framebuffer without depth attachment in shadow mapping

In my shadow map implementation, i am attaching color attachment to my fbo and i don't have any depth attachment. I have depth test enabled for rendering onto that FBO. With this implementation I get shadows correctly. I am wondering how it works without depth attachment. Can somebody explain me this?
I use color attachment to store my depth values as
color = vec4(gl_FragCoord.z,gl_FragCoord.z,gl_FragCoord.z,1.0);
This resembles no depth attachment I have ever seen (I realize you are trying to use a color attachment in its place); you are shoehorning four components into something that only needs one. There is defined behavior for reading from the 2nd, 3rd and 4th components of a depth attachment even though they do not exist, but writing to them is effectively meaningless.
If you intend to use a color texture to serve as a depth texture, then make sure it has high single-component precision (e.g. try something like GL_R32F) and do not waste storage with the 2nd, 3rd and 4th components. Alternatively, you could pack parts of a 32-bit, 24-bit or 16-bit fixed-point value across multiple components and unpack them later - this is pretty unorthodox on anything modern.
I am wondering how it works without depth attachment.
Generally it will not work.
You have just told us you have no depth attachment but the depth test is enabled ... what is that going to accomplish?
You may not want to draw to a depth texture for some reason, but you are at the very least, going to need a renderbuffer depth attachment for there to be anything in the framebuffer to actually test against.

How to read pixels from framebuffer object

I want to read the depth component of a scene rendered to a framebuffer object. I initially used glReadPixels() but found that it could only read pixels from the default framebuffer.
The answers to some relevant questions on this website suggest using PBO, but I haven't tried it yet. It seems that the PBO reading is asynchronous, therefore, using which command can synchronize the reading at the end?
A PBO won't help you here, because those are just a different kind of buffer to read into (instead of memory on the host into memory of the OpenGL implementation).
The usual way to go about making a depth component back-readable in OpenGL is to use a depth texture, attached to the depth attachment and after rendering using glGetTexImage to retrieve the date.
In the case of a normal color attachment you could use glReadPixels with a previous call to glReadBuffer to select the GL_COLOR_ATTACHMENT<i> of the bound FBO.

Is it possible to attach the default renderbuffer to a FBO?

I'm considering refactoring a large part of my rendering code and one question popped to mind:
Is it possible to render to both the screen and to a texture using multiple color attachments in a Frame Buffer Object? I cannot find any information if this should be possible or not even though it has many useful applications. I guess it should be enough to bind my texture as color attachment0 and renderbuffer 0 to attachment1?
For example I want to make an interactive application where you can "draw" on a 3D model. I resolve where the user draws by rendering the UV-coordinates to a texture so I can look up at the mouse-coordinates where to modify the texture. In my case it would be fastest to have a shader that both draws the UV's to the texture and the actual texture to the screen in one pass.
Are there better ways to do this or am I on the right track?
There is no such thing as "default renderbuffer" in OpenGL. There is the window system provided default frame buffer with reserved name zero, but that basically means "no FBO enabled". So no, unfortunately normal OpenGL provides no method to somehow use its color buffer as a color attachment to any other FBO. I'm not aware of any extensions that could possible provide this feature.
With render buffers there is also the reserved name zero, but it's only a special "none" variable and allows unbinding render buffers.