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.
Related
I succeeded in render to texture with Texturebuffer, using VAO and shaders.
But FBO has another options for color buffer, it's Renderbuffer. I searched a lot on the internet, but cannot found any example related to draw Renderbuffer as Texturebuffer with shaders
If I ain't wrong, Renderbuffer is released in OpenGL 3.30, and it's faster than Texturebuffer.
Can I use Renderbuffer as Texturebuffer? (stupid question huh? I think it should be absolutely, isn't it?)
If yes, please lead me or give any example to draw render buffer as texture buffer.
My target is just for study, but I'd like to know is that a better way to draw textures? Should we use it frequently?
First of all, don't use the term "texture buffer" when you really just mean texture. A "buffer texture"/"texture buffer object" is a different conecpt, completely unrelated here.
If I ain't wrong, Renderbuffer is released in OpenGL 3.30, and it's faster than Texturebuffer.
No. Renderbuffers were there when FBOs were first invented. One being faster than the other is not generally true either, but these are implementation details. But it is also irrelevant.
Can I use Renderbuffer as Texturebuffer? (stupid question huh? I think it should be absolutely, isn't it?)
Nope. You cant use the contents of a renderbuffer directly as a source for texture mapping. Renderbuffesr are just abstract memory regions the GPU renders to, and they are not in the format required for texturing. You can read back the results to the CPU using glReadPixels, our you could copy the data into a texture object, e.g. via glCopyTexSubImage - but that would be much slower than directly rendering into textures.
So renderbuffers are good for a different set of use cases:
offscreen rendering (e.g. where the image results will be written to a file, or encoded to a video)
as helper buffers during rendering, like the depth buffer or stencil buffer, where you do not care anbout the final contents of these buffers anyway
as intermediate buffer when the image data can't be directly used by the follwoing steps, e.g. when using multisampling, and copying the result to a non-multisampled framebuffer or texture
It appears that you have your terminology mixed up.
You attach images to Framebuffer Objects. Those images can either be a Renderbuffer Object (this is an offscreen surface that has very few uses besides attaching and blitting) or they can be part of a Texture Object.
Use whichever makes sense. If you need to read the results of your drawing in a shader then obviously you should attach a texture. If you just need a depth buffer, but never need to read it back, a renderbuffer might be fine. Some older hardware does not support multisampled textures, so that is another situation where you might favor renderbuffers over textures.
Performance wise, do not make any assumptions. You might think that since renderbuffers have a lot fewer uses they would somehow be quicker, but that's not always the case. glBlitFramebuffer (...) can be slower than drawing a textured quad.
I need to gather information about the target used in a texture attachment of an FBO in order to copy it to another FBO.
As far as OpenGL ES 2.0 is concerned, I can use glGetFramebufferAttachmentParameter[if]v() and, since OpenGL ES 2.0 only supports GL_TEXTURE_2D and GL_TEXTURE_CUBE_MAP, the information returned is enough to determine the texture target that was used (when it's not a cube map face, it is a GL_TEXTURE_2D since it can't be anything else).
On the desktop, however, things change:
Because then we have GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_RECTANGLE, GL_TEXTURE_3D, and the 6 cube map faces as valid targets for an FBO's texture attachment, and while the 6 cube map faces and GL_TEXTURE_3D targets are easy to tell (since there are specific queries for cube map faces and layered textures), the same does not apply to the remaining targets: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_2D_MULTISAMPLE, and GL_TEXTURE_RECTANGLE, at least as far as the manual pages are concerned. Therefore, how would I be able to tell which of these 4 targets was used in a texture attachment?
The need to copy an FBO stems from the fact that FBOs are not shared between contexts, the implementation creates screen FBOs in the main thread, and I want to use them in child threads dedicated to each screen so as to not stall the main thread with render loops and thus keep the application responsive to UI events. Caching state is both undesirable and unfeasible in this case; undesirable because it cuts through otherwise distinct concerns of the application when the client library (which only concern is to serve as a communication API between the application and the OpenGL server) is in a much better position to cache state itself, and unfeasible since in this case I don't even control some of the concerns in my application, as mentioned before.
Right now this is a theoretical question, because the implementation I'm working on only supports OpenGL ES 2.0, but I would rather write future-proof code where I can be certain about the exact texture target used as an FBO attachment than code that works only because the number of available options is limited to the point where I can figure out which option was chosen by excluding those that weren't, an approach that, as demonstrated above, wouldn't work on the feature-rich desktop versions and may not work on future OpenGL ES version.
OpenGL has no solution for the problem you're having. There is no way to look at a texture object and know what target it is, nor is there a way to know what the textarget parameter of a texture that was attached to an FBO was. Generally speaking, you are expected to keep track of the texture object's target, just as you're expected to keep track of the texture object's name (the GLuint you get back from glGenTextures).
The best way to handle this would be to simply ask the client library what textures and texture targets it adds to it's FBO. If you can't get this client library to provide you this information, then you can't do what you need to do.
I recently read that simply switching the render targets of a framebuffer object is much faster than switching framebuffer object.
As extreme as it sounds, does this this mean I should only ever use one framebuffer object and only switchout it's targets?
EDIT: I changed 'swapping' to 'switching' to avoid confusion. By switching I mean binding a new framebuffer in place of the old one. Not to be confused with the SwapBuffers() call used to swap the front- and backbuffers.
EDIT: this answer is probably wrong. Read the comments below.
It's faster to switch framebuffer-attachable textures than switching between framebuffers (FBOs). More here http://www.songho.ca/opengl/gl_fbo.html
There are limits to how many attachments a FBO can have though.
In what cases would I want to have a renderbuffer attachment in an OpenGL FBO, instead of a texture attachment, besides for the default framebuffer? As, a texture attachment seems far more versatile.
Textures provide more features to you (sampling!, formats variety) and hence are more likely subject to performance loss.
The answer is simple: use Textures wherever you have to sample from the surface (no alternatives).
Use Render buffers wherever you don't need to sample. The driver may or may not decide to store your pixel data more effectively based on your expressed intention of not doing sampling.
You can use GL blitting afterwards to do something with the result.
Extending the question to OpenGL|ES, another reason to use RenderBuffers instead of textures is also that textures may not be supported in some configurations and prevent you from building a valid FBO. I specifically think about depth textures, which are not natively supported on some hardware, for instance nVidia Tegra 2/3.
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.