Creating Multisample Texture Correctly - opengl

For standard OpenGL textures, the filtering state is part of the texture, and must be defined when the texture is created. This leads to code like:
glGenTextures(1,&_texture_id);
glBindTexture(GL_TEXTURE_2D,_texture_id);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexImage2D(...);
This works perfectly. I am trying to make a multisampled texture (for use in a FBO). The code is very similar:
glGenTextures(1,&_texture_id);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,_texture_id);
glTexParameterf(GL_TEXTURE_2D_MULTISAMPLE,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D_MULTISAMPLE,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexImage2DMultisample(...);
I am using a debug context, and with this code the first glTexParameterf(...) call causes:
GL_INVALID_ENUM error generated. multisample texture targets doesn't support sampler state
I don't know what this is supposed to mean. Notice that multisampled textures only support nearest filtering. I am specifying this. I noticed that for some of the calls (in particular glTexParameterf(...)), the GL_TEXTURE_2D_MULTISAMPLE is not a listed input in the documentation (which would indeed explain the invalid enum error if they're actually invalid, not just forgotten). However, if it is not accepted, then how am I supposed to set nearest filtering?

You do not need to set nearest filtering because multisample textures are not filtered at all. The specification (section 8.10) does list GL_TEXTURE_2D_MULTISAMPLE as a valid target for glTexParameteri (which you should use instead of glTexParameterf for integer parameters), but lists among possible errors:
An INVALID_ENUM error is generated if target is either TEXTURE_2D_MULTISAMPLE
or TEXTURE_2D_MULTISAMPLE_ARRAY, and pname is any sampler
state from table 23.18.

Related

QOpenGLFrameBufferObject: binding texture name from texture() gives InvalidOperation error

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.

Render to texture - texture formats and parameters?

When I render to a texture (stored in a bound framebuffer object), do any of the following texture parameters matter?
GL_TEXTURE_WRAP_S
GL_TEXTURE_WRAP_T
GL_TEXTURE_MIN_FILTER
GL_TEXTURE_MAG_FILTER
It's also redundant to generate mipmaps, right? (Might be a stupid question, but I'm just making sure!)
What about data types (the type parameter)?
Does type have to be GL_FLOAT? If not, what's the difference between specifying type as GL_FLOAT and GL_UNSIGNED_BYTE?
Also, every doc I find on the web regarding Texture2D info (e.g. https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml) is missing some info. (namely the GL_DEPTH_COMPONENT16/24/32, and GL_RGB16 flags. other sources miss a lot more).
Is there a source for complete info on these stuff? (preferably specialized for the render-to-texture technique)
When I render to a texture (stored in a bound framebuffer object), do any of the following texture parameters matter?
No. While those parameters can be set in a way that breaks Texture Completeness, they do not affect Framebuffer Object Completeness. No texture or sampling parameters can affect framebuffer completeness.
What about data types (the type parameter)? Does type have to be GL_FLOAT? If not, what's the difference between specifying type as GL_FLOAT and GL_UNSIGNED_BYTE?
Even if you are transferring no bytes of data (ie: passing nullptr), you must provide pixel transfer parameters that are legal values. If you don't, then your call to glTexImage2D will fail with an error.
For example, from the OpenGL Specification version 4.5:
An INVALID_OPERATION error is generated if one of the base internal
format and format is DEPTH_COMPONENT or DEPTH_STENCIL, and the other
is neither of these values.
So your internal format and pixel transfer format must at least be able to talk to one another, even if they're never actually used. So if you're making a depth/stencil texture, you must use GL_DEPTH_STENCIL as the pixel transfer format.
Or you can just stop screwing around with bad APIs and use glTexStorage.

Possible to find internal format of texture in shader?

Is it possible to find the internal format of a texture within the shader (glsl)?
For example, if I have a texture with the format GL_RG, is it possible to recognize in the shader that the blue and alpha value are "constant" and can be ignored?
I know I can use a uniform to pass the texture type from c++ to the shaders. But is there an "intrinsic" way to find out from within the shader?
No, I don't believe there is anything that would give you this information directly.
Looking at the latest GLSL spec (4.50 at this time), I would expect a hypothetical function to get this information to be listed in section "8.9.1. Texture Query Functions" starting on page 158. But the only functions listed there are:
textureSize: Get size of texture.
textureQueryLod: Get the level of detail used for the given texture coordinates.
textureQueryLevels: Get the number of mipmap levels in the texture.
textureSamples: Get the number of samples for a multisampled texture.
So unless there is something completely different I missed, what you're looking for does not exist.

OpenGL texture terminology/conceptual confusion

I've found a lot of resources that tell you what to type to get a texture on screen, but would like a higher level conceptual understanding of what the openGL API is "doing" and what all of the differences in terminology "mean".
I'm going to do my best to explain what I've picked up, but would love any corrections/additions, or pointers to resources where I can read further (and just a note that I've found the documentation of the actual API calls to just reference themselves in circles and be conceptually lacking).
glGenTextures- this won't actually allocate any memory for the data of a texture on the graphics card (you just tell it "how many" textures you want it to generate, so it doesn't know anything about the size...), but instead sets kind of a "name" aside so you can reference given textures consistently (I've been thinking of it as kind of "allocating a pointer").
glBindTexture- use the "name" generated in glGenTexture to specify that "we're now talking about this texture for future API calls until further notice", and further, we're specifying some metadata about that "pointer" we've allocated saying whether the texture it points to (/will point to) is of type GL_TEXTURE_2D or ..._3D or whatever. (Is it just me, or is it weird that this call has those two seemingly totally different functionalities?)
glTexParameter- sets other specified metadata about the currently "bound" texture. (I like this API as it seems pretty self explanatory and lets you set metadata explicitly... but I wonder why letting OpenGL know that it's a GL_TEXTURE_2D isn't part of THIS call, and not the previous? Especially because you have to specify that it's a GL_TEXTURE_2D every time you call this anyways? And why do you have to do that?)
glTexImage2D- allocates the memory for the actual data for the texture on the graphics card (and optionally uploads it). It further specifies some metadata regarding how it ought be read: its width, height, formatting (GL_RGB, GL_RGBA, etc...). Now again, why do I again have to specify that it's a GL_TEXTURE_2D when I've done it in all the previous calls? Also, I guess I can understand why this includes some metadata (rather than offloading ALL the texture metadata calls to glTexParameter as these are pretty fundamental/non-optional bits of info, but there are also some weird parameters that seem like they oughtn't have made the cut? oh well...)
glActiveTexture- this is the bit that I really don't get... So I guess graphics cards are capable of having only a limited number of "texture units"... what is a texture unit? Is it that there can only be N texture buffers? Or only N texture pointers? Or (this is my best guess...) there can only be N pointers being actively read by a given draw call? And once I get that, where/how often to I have to specify the "Active Texture"? Does glBindTexture associate the bound texture with the currently active texture? Or is it the other way around (bind, then set active)? Or does uploading/allocating the graphics card memory do that?
sampler2D- now we're getting into glsl stuff... So, a sampler is a thing that can reference a texture from within a shader. I can get its location via glGetUniformLocation, so I can set which texture that sampler is referencing- does this correspond to the "Active Texture"? So if I want to talk about the texture I've specified as GL_TEXTURE0, I'd call glUniform1i(location_of_sampler_uniform,0)? Or are those two different things?
I think that's all I got... if I'm obviously missing some intuition or something, please let me know! Thanks!
Let me apologize for answering with what amounts to a giant wall of text. I could not figure out how to format this any less obnoxious way ;)
glGenTextures
this won't actually allocate any memory for the data of a texture on the graphics card (you just tell it "how many" textures you want it to generate, so it doesn't know anything about the size...), but instead sets kind of a "name" aside so you can reference given textures consistently (I've been thinking of it as kind of "allocating a pointer").
You can more or less think of it as "allocating a pointer." What it really does is reserve a name (handle) in the set of textures. Nothing is allocated at all at this point, basically it just flags GL to say "you can't hand out this name anymore." (more on this later).
glBindTexture
use the "name" generated in glGenTexture to specify that "we're now talking about this texture for future API calls until further notice", and further, we're specifying some metadata about that "pointer" we've allocated saying whether the texture it points to (/will point to) is of type GL_TEXTURE_2D or ..._3D or whatever. (Is it just me, or is it weird that this call has those two seemingly totally different functionalities?)
If you will recall, glGenTextures (...) only reserves a name. This function is what takes the reserved name and effectively finalizes it as a texture object (the first time it is called). The type you pass here is immutable, once you bind a name for the first time, it has to use the same type for every successive bind.
Now you have finally finished allocating a texture object, but it has no data store at this point -- it is just a set of states with no data.
glTexParameter
sets other specified metadata about the currently "bound" texture. (I like this API as it seems pretty self explanatory and lets you set metadata explicitly... but I wonder why letting OpenGL know that it's a GL_TEXTURE_2D isn't part of THIS call, and not the previous? Especially because you have to specify that it's a GL_TEXTURE_2D every time you call this anyways? And why do you have to do that?)
I am actually not quite clear what you are asking here -- maybe my explanation of the previous function call will help you? But you are right, this function sets the state associated with a texture object.
glTexImage2D
allocates the memory for the actual data for the texture on the graphics card (and optionally uploads it). It further specifies some metadata regarding how it ought be read: its width, height, formatting (GL_RGB, GL_RGBA, etc...). Now again, why do I again have to specify that it's a GL_TEXTURE_2D when I've done it in all the previous calls? Also, I guess I can understand why this includes some metadata (rather than offloading ALL the texture metadata calls to glTexParameter as these are pretty fundamental/non-optional bits of info, but there are also some weird parameters that seem like they oughtn't have made the cut? oh well...)
This is what allocates the data store and (optionally) uploads texture data (you can supply NULL for the data here and opt to finish the data upload later with glTexSubImage2D (...)).
You have to specify the texture target here because there are half a dozen different types of textures that use 2D data stores. The simplest way to illustrate this is a cubemap.
A cubemap has type GL_TEXTURE_CUBE_MAP, but you cannot upload its texture data using GL_TEXTURE_CUBE_MAP -- that is nonsensical. Instead, you call glTexImage2D (...) while the cubemap is bound to GL_TEXTURE_CUBE_MAP and then you pass something like GL_TEXTURE_CUBE_MAP_POSITIVE_X to indicate which of the 6 2D faces of the cubemap you are referencing.
glActiveTexture
this is the bit that I really don't get... So I guess graphics cards are capable of having only a limited number of "texture units"... what is a texture unit? Is it that there can only be N texture buffers? Or only N texture pointers? Or (this is my best guess...) there can only be N pointers being actively read by a given draw call? And once I get that, where/how often to I have to specify the "Active Texture"? Does glBindTexture associate the bound texture with the currently active texture? Or is it the other way around (bind, then set active)? Or does uploading/allocating the graphics card memory do that?
This is an additional level of indirection for texture binding (GL did not always have multiple texture units and you would have to do multiple render passes to apply multiple textures).
Once multi-texturing was introduced, binding a texture actually started to work this way:
glBindTexture (target, name) => ATIU.targets [target].bound = name
Where:
* ATIU is the active texture image unit
* targets is an array of all possible texture types that can be bound to this unit
* bound is the name of the texture bound to ATIU.targets [target]
The rules since OpenGL 3.0 have been, you get a minimum of 16 of these for every shader stage in the system.
This requirement allows you enough binding locations to maintain a set of 16 different textures for each stage of the programmable pipeline (vertex,geometry,fragment -- 3.x, tessellation control / evaluation -- 4.0). Most implementations can only use 16 textures in a single shader invocation (pass, basically), but you have a total of 48 (GL3) or 80 (GL4) places you can select from.
sampler2D
now we're getting into glsl stuff... So, a sampler is a thing that can reference a texture from within a shader. I can get its location via glGetUniformLocation, so I can set which texture that sampler is referencing- does this correspond to the "Active Texture"? So if I want to talk about the texture I've specified as GL_TEXTURE0, I'd call glUniform1i(location_of_sampler_uniform,0)? Or are those two different things?
Yes, the samplers in GLSL store indices that correspond to GL_TEXTUREn, where n is the value you have assigned to this uniform.
These are not regular uniforms, mind you, they are called opaque types (the value assigned cannot be changed/assigned from within a shader at run-time). You do not need to know that, but it might help to understand that if the question ever arises:
"Why can't I dynamically select a texture image unit for my sampler at run-time?" :)
In later versions of OpenGL, samplers actually became state objects of their own. They decouple some of the state that used to be tied directly to texture objects but had nothing to do with interpreting how the texture's data was stored. The decoupled state includes things like texture wrap mode, min/mag filter and mipmap levels. Sampler objects store no data.
This decoupling takes place whenever you bind a sampler object to a texture image unit - that will override the aforementioned states that are duplicated by every texture object.
So effectively, a GLSL sampler* references neither a texture nor a sampler; it references a texture image unit (which may have one or both of those things bound to it). GLSL will pull sampler state and texture data accordingly from that unit based on the declared sampler type.

OpenGL Texture Usage

So recently I started reading through OpenGL wiki articles. This is how I picture OpenGL texturing described from here. Though, several points are not clear yet.
Will following statements be true, false or depends?
Binding two textures to same texture unit is impossible.
Binding two samplers to same texture unit is impossible.
Binding one texture to two different texture units is impossible.
Binding one sampler to two different texture units is impossible.
It is application's responsibility to be clear about what sampler type is passed to what uniform variable.
It is shader program's responsibility to make sure to take sampler as correct type of uniform variable.
number of texture units are large enough. Let each mesh loaded to application occupy as much texture unit as it please.
Some Sampler parameters are duplicate of texture parameters. They will override texture parameter setting.
Some Sampler parameters are duplicate of sampler description in shader program. Shader program's description will override samplers parameters.
I'm going through your statements in the following. Sometimes I will argue with quotes from the OpenGL 4.5 core profile specification. None of that is specific to GL 4.5, I just chose it because that is the most recent version.
1. Binding two textures to same texture unit is
impossible.
If I'd say "false", it would be probably misleading. The exact statement would be "Binding two textures to the same target of the same texture unit is impossible." Technically, you can say, bind a 2D texture and a 3D texture to the same unit. But you cannot use both in the same draw call. Note that this is a dynamic error condition which depends on what values you set the sampler uniforms to. Quote from section 7.10 "Samplers" of the GL spec:
It is not allowed to have variables of different sampler types
pointing to the same texture image unit within a program object. This
situation can only be detected at the next rendering command issued
which triggers shader invocations, and an INVALID_OPERATION error will
then be generated.
So the GL will detect this error condition as soon as you actually try to draw something (or otherwise trigger shader invocations) with that shaders while you configured it such that two sampler uniforms reference different targets of the same unit. But it is not an error before. If you temporarily set both uniforms to the same value but do not try to draw in that state, no error is ever generated.
2. Binding two samplers to same texture unit is impossible.
You probably mean Sampler Objects (as opposed to just "sampler" types in GLSL), so this is true.
3. Binding one texture to two different texture units is impossible.
False. You can bind the same texture object to as many units as there are available. However, that is quite a useless operation. Back in the days of the fixed-function pipeline, there were some corner cases where this was of limited use. For example, I've saw someone binding the same texture twice and use register combiners to multiply both together, because he needed some square operation. However, with shaders, you can sample the texture once and do anything you want with the result, so there is really no use case left for this.
4. Binding one sampler to two different texture units is impossible.
False. A single sampler object can be referenced by multiple texture units. You can just create a sampler object for each sampling state you need, no need to create redundant ones.
5. It is application's responsibility to be clear about what sampler type is passed to what uniform variable.
6. It is shader program's responsibility to make sure to take sampler as correct type of uniform variable.
I'm not really sure what exaclty you are asking here. The sampler variable in your shader selectes the texture target and must also match the internal data fromat of the texture object you want to use (i.e. for isampler or usampler, you'll need unnormalized integer texture formats otherwise results are undefined).
But I don't know what "what sampler type is passed to what uniform variable" is supposed to mean here. As far as the GL client side is concerned, the opaque sampler uniforms are just something which can be set to the index of the texture unit which is to be used, and that is done as an integer via glUniform1i or the like. There is no "sampler type" passed to a uniform variable.
7. number of texture units are large enough. Let each mesh loaded to application occupy as much texture unit as it please.
Not in the general case. The required GL_MAX_TEXTURE_IMAGE_UNITS (which defines how many different texture units a fragment shader can access) by the GL 4.5 spec is just 16. (There are separate limits per shder stage, so there is GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS and so on. They are all required to be at least 16 in the current spec.)
Usually, you have to switch textures inbetween draw calls. The usage of array textures and texture atlasses might allow one to further reduce the number of necessary state switches (and, ultimately, draw calls).
Very modern GPUs also support GL_ARB_bindless_texture, which completely bypasses the "texture unit" layer of indirection and allows the shader to directly reference a texture object by some opaque handle (which basically boils down to referencing some virtual GPU memory address under the hood). However, that feature is not yet part of the OpenGL standard.
8. Some Sampler parameters are duplicate of texture parameters. They will override texture parameter setting.
Yes. Traditionally, there were no separate sampler objects in the GL. Instead, the sampler states like filtering or wrap modes were part of the texture object itself. But modern hardware does not operate this way, so the sampler objects API has been introduced as the GL_ARB_sampler_objects extension (nowadays, a core feature of GL). If a sampler object is bound to a texture unit, its settings will override the sampler state present in the texture object.
9. Some Sampler parameters are duplicate of sampler description in shader program. Shader program's description will override samplers parameters.
I'm not sure what you mean by that. What "sampler descripitons" does a shader program define? There is only the declaration of the uniform and possibly the initialization via layout(binding=...). However, that is just the initial value. The client can update that any time by setting the uniform to another value, so that is not really "overriding" anything. But I'm not sure if you mean that.