I would like to remember a current texture state in OpenGL 1.x and later restore it. I can use glIsEnabled to check which texture types are active.
Does it make sense to have enabled more than one text type, for example, GL_TEXTURE_2D and GL_TEXTURE_CUBE_MAP?
glGet* function allows to get a current texture id, for example, GL_TEXTURE_BINDING_2D but to bind previous texture I also need to know appropriate target for glBindTexture.
How to achieve it?
Related
If my understanding is correct, a texture unit has a number of targets (GL_TEXTURE_2D etc.) that I can bind textures to. I can change the currently active texture unit with glActiveTexture. When I'm calling glBindTexture, I bind the specified texture object to the specified target of the currently active texture unit, right?
When I want to later change the parameters of a texture or call a function like glTexSubImage2D, is it enough to call glActiveTexture with the texture unit that my texture is bound to? Or do I have to call glBindTexture everytime, even if the texture is already bound to a unit?
So long as you know what state is bound to which unit, you can rely on just changing glActiveTexture to switch to the right unit to find it.
However, you should not rely upon this for this purpose. Not because OpenGL is unreliable, but because you may be wrong about what you think you've bound to which unit.
Furthermore, it blurs the line between binding a texture to render with it and binding a texture to modify it. You want the two to be entirely separate. First, because modifying a texture's state in the rendering loop (where you're binding it to modify it) is bad form and likely to be slow. And second, so that when it comes time to adopt GL 4.5 and DSA, you can do so quickly and efficiently.
You can think of Texture unit as pipes present on GPU .
There are many such texture units present on GPU. By calling glActivateTexture() you are telling OpenGL driver to tell GPU that which ever texture I will bind next load/connect it in mentioned texture unit.By saying glBindTexture() you are telling driver that whatever operations I am about to do, please do it on the texture I have bound. As once you have call glTextureImage2D your texture is residing in driver memory and hence you dont have direct access to it. So driver has given you handle to texture object which you bind and tell driver which resource I am talking about.
So when ever you render its always good to do both activate texture unit and then bind your texture. As you have done activate first and bind later the texture will be automatically bound to unit you have given.
If you dont mention texture unit by default GL_TEXTURE0 will be used and hence sometimes it could be confusing.
Hope this helps.
In my application I have a module that manages rendering using OpenGL, and renders the results into QOpenGLFrameBufferObjects. I know this much works, because I'm able to save their contents using QOpenGLFrameBufferObject::toImage() and see the render.
I am now attempting to take the texture ID returned from QOpenGLFrameBufferObject::texture(), bind it as a normal OpenGL texture and render it into a QOpenGLWidget viewport using a fullscreen quad. (I'm using this two-step method because I'm not aware of a way to get around the fact that QOpenGLWidgets each work in their own context, but that's a different story.)
The problem here is that glBindTexture() returns InvalidOperation when I call it. According to the OpenGL documentation, this is because "[The] texture was previously created with a target that doesn't match that of [the input]." However, I created the frame buffer object by passing GL_TEXTURE_2D into the constructor, and am passing the same in as the target to glBindTexture(), so I'm not sure where I'm going wrong. There isn't much documentation online about how to correctly use QOpenGLFrameBufferObject::texture().
Other supplementary information, in case it helps:
The creation of the frame buffer object doesn't set any special formats. They're left at whatever defaults Qt uses. As far as I know, this means it also has no depth or stencil attachments as of yet, though once I've got the basics working this will probably change.
Binding the FBO before binding its texture doesn't seem to make a difference.
QOpenGLFrameBufferObject::isValid() returns true;
Calling glIsTexture() on the texture handle returns false, but I'm not sure why this would be given that it's a value provided to me by Qt for the purposes of binding an OpenGL texture. The OpenGL documentation does mention that "a name returned by glGenTextures, but not yet associated with a texture by calling glBindTexture, is not the name of a texture", but here I can't bind it anyway.
I'm attempting to bind the texture in a different context to the one the FBO was created in (ie. the QOpenGLWidget's context instead of the render module's context).
I'll provide some code, but a lot of what I have is specific to the systems that exist in the rendering module, so there's only a small amount of relevant OpenGL code.
In the render module context:
QOpenGLFrameBufferObject fbo = new QOpenGLFrameBufferObject(QSize(...), GL_TEXTURE_2D);
// Do some rendering in this context later
In the QOpenGLWidget context, after having rendered to the frame buffer in the rendering module:
GLuint textureId = fbo->texture();
glBindTexture(GL_TEXTURE_2D, textureId)) // Invalid operation
EDIT: It turns out the culprit was that my contexts weren't actually being shared, as I'd misinterpreted what the Qt::AA_ShareOpenGLContexts application attribute did. Once I made them properly shared the issue was fixed.
When calling glBindFramebuffer(GLenum target, GLuint framebuffer);, I know that target can either be GL_READ_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER, or GL_FRAMEBUFFER which is both.
However, when I attach texture or Renderbuffer objects to the framebuffer, I must provide a binding target as well.
My question is, when I attach anything to a framebuffer through binding target target, does it stay constant?
This means when a renderbuffer is attached to a framebuffer through binding point GL_DRAW_FRAMEBUFFER, it will always be the target of drawing operations, and if I want that renderbuffer to be read from then I must call glFramebufferRenderbuffer() again with target set to GL_READ_FRAMEBUFFER this time.
Can anyone confirm this? I'm asking because I'm trying to encapsulate all these in C++ classes.
This means when a renderbuffer is attached to a framebuffer through binding point GL_DRAW_FRAMEBUFFER, it will always be the target of drawing operations, and if I want that renderbuffer to be read from then I must call glFramebufferRenderbuffer() again with target set to GL_READ_FRAMEBUFFER this time.
No. The attachments are per-FBO state, they have nothing to do with the binding point the FBO is bound.
An object may be bound to semantically different binding targets, but the object itself defines all of it's state. For example, you might load data to an buffer which is bound as GL_PIXEL_UNPACK_BUFFER, and later use this data as vertex attributes by binding it as GL_VERTEX_ARRAY_BUFFER.
However, when I attach texture or Renderbuffer objects to the framebuffer, I must provide a binding target as well.
Well, that is beacuse traditional GL uses bind to modify semantics. If you want to manipulate the state of any object, you must bind it to some target (matching the object type, of course), and all state setting functions will reference the object indirectly by addressing the target. This does not meen that the modifications have anything to do with the binding point.
Bind-to-modify his has been an often criticised principle of OpenGL. For a long time, the EXT_direct_state_access extension had been implemented by some vendors, to address this issue. It provides functions to directly reference the objects instead of indirectly using the binding points. In your example, glNamedFramebufferRenderbufferEXT will allow you to directly attach a renderbuffer without binding the FBO first.
Finally with OpenGL 4.5, direct state access was promoted a core feature of OpenGL, and the ARB_direct_state_access was created to allow implementors to provide the final API (which is different from the EXT version in some aspects) for earlier GL versions. Now there is the official glNamedFramebufferRenderbuffer() function.
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.
How do I turn off a texture unit, or at least prevent its state changing when I bind a texture? I'm using shaders so there's no glDisable for this I don't think. The problem is that the chain of events might look something like this:
Create texture 1 (implies binding it)
Use texture 1 with texture unit 1
Create texture 2 (implies binding it)
Use texture 2 with texture unit 2
, but given glActiveTexture semantics, it seems this isn't possible, because the create of texture 2 will become associated with the state of texture unit 1, as that was the last unit I called glActiveTexture on. i.e. you have to write:
Create texture 1
Create texture 2
Use texture 1 with texture unit 1
Use texture 2 with texture unit 2
I've simplified the example of course, but the fact that creating and binding a texture can incidentally affect the currently active texture unit even when you are only binding the texture as part of the creation process is something that makes me somewhat uncomfortable. Unless of course I've made an error here and there's something I can do to disable state changes in the current glActiveTexture?
Thanks for any assistance you can give me here.
This is pretty much something you just have to learn to live with in OpenGL. GL functions only affect the current state. So to modify an object, you must bind it to the current state, and modify it.
In general however, you shouldn't have a problem. There is no reason to create textures in the same place where you're binding them for use. The code that actually walks your scene and binds textures for rendering should never be creating textures. The rendering code should establish all necessary state for each rendering (unless it knows that all necessary state was previously established in this rendering call). So it should be binding all of the textures that each object needs. So previously created textures will be evicted.
And in general, I would suggest unbinding textures after creation (ie: glBindTexture(..., 0)). This prevents them from sticking around.
And remember: when you bind a texture, you also unbind whatever texture was currently bound. So the texture functions will only affect the new object.
However, if you want to rely on an EXT extension, there is EXT_direct_state_access. It is supported by NVIDIA and AMD, so it's fairly widely available. It allows you to modify objects without binding them, so you can create a texture without binding it.