Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL4.5 - bind multiple textures and samplers

enter image description here

I'm trying to understand Textures, Texture Units and Samplers in OpenGL 4.5. I'm attaching a picture of what I'm trying to figure out. I think in my example everything is correct, but I am not so sure about the 1D Sampler on the right side with the question mark.

So, I know OpenGL offers a number of texture units/binding points where textures and samplers can be bound so they work together.

Each of these binding points can support one of each texture targets (in my case, I'm binding targets GL_TEXTURE_2D and GL_TEXTURE_1D to binding point 0, and another GL_TEXTURE_2D to binding point 1).

Additionally, samplers can be bound to these binding points in much the same way (I have bound a 2D sampler to binding point 0 in the pic).

The functions to perform these operations are glBindTextureUnit and glBindSampler.

My initial thought was to bind the 1D sampler to binding point 0, too, and in shader land do the matching based on the binding point and the type of the sampler:

layout (binding = 0) uniform sampler1D tex1D;
layout (binding = 0) uniform sampler2D tex2D;

Quoting the source:

Each texture image unit supports bindings to all targets. So a 2D texture and an array texture can be bound to the same image unit, or different 2D textures can be bound in two different image units without affecting each other. So which texture gets used when rendering? In GLSL, this depends on the type of sampler that uses this texture image unit.

but I found the following statement:

[..] sounds suspiciously like you can use the same texture image unit for different samplers, as long as they have different texture types. Do not do this. The spec explicitly disallows it; if two different GLSL samplers have different texture types, but are associated with the same texture image unit, then rendering will fail. Give each sampler a different texture image unit.

So, my question is, what is the purpose of binding different texture targets to the same binding point at all, if ultimately a single sampler is going to be bound to that binding point, forcing you to choose?

The information I'm quoting: https://www.khronos.org/opengl/wiki/Texture#Texture_image_units

like image 653
Carlos Romero Avatar asked Jul 21 '17 09:07

Carlos Romero


People also ask

What is sampler2D?

A sampler2D is used to do lookup in a standard texture image; a samplerCube is used to do lookup in a cubemap texture (Subsection 5.3. 4). The value of a sampler variable is a reference to a texture unit. The value tells which texture unit is invoked when the sampler variable is used to do texture lookup.

What is Gl_repeat?

GL_REPEAT : The integer part of the coordinate will be ignored and a repeating pattern is formed. GL_MIRRORED_REPEAT : The texture will also be repeated, but it will be mirrored when the integer part of the coordinate is odd. GL_CLAMP_TO_EDGE : The coordinate will simply be clamped between 0 and 1 .

What is GL_TEXTURE_2D?

GL_TEXTURE_2D: Images in this texture all are 2-dimensional. They have width and height, but no depth. GL_TEXTURE_3D: Images in this texture all are 3-dimensional. They have width, height, and depth. GL_TEXTURE_RECTANGLE: The image in this texture (only one image.


1 Answers

So why does this exist? Well...

Once upon a time, there were no texture units (this is why glActiveTexture is a separate function from glBindTexture). Indeed, there weren't even texture objects in OpenGL 1.0. But there still needed to be different kinds of textures. You still needed to be able to create data for a 2D texture and a 3D texture. So they came up with the texture target distinction, and they used glEnables to determine which target would be used in a rendering operation.

When texture objects came into being in GL 1.1, they had to decide on the relationship between a texture object and the target. They decided that once an object was bound to a target, it was permanently associated with that target. Because of the aforementioned need to have multiple textures of different types, with the old enable functionality, it was decided that each target represented a separate object binding point. And they made you repeat the binding point in glBindTexture, so that it would be clear to the reader of the code which binding point's data you were disturbing.

Cut to OpenGL 1.2, when multitexture came out. So now they need you to be able to bind multiple textures of the same target, but to different "units". But they couldn't change glBindTexture to specify a particular unit; that would be a backwards-incompatible change.

Now, they could have completely revamped how textures work, creating a new binding function specifically for multitexturing and the like. But the OpenGL ARB loves backwards compatibility; they like making the old API functions work, no matter what the resulting API looks like. So instead, they decided that a texture unit would be an entire set of bindings, with each set having an enable state saying which target was the one to be used. And you switch between units with glActiveTexture.

Of course, once shaders came about, you can see how this all changes. The enable state becomes the sampler type in the shader. So now there's no explicit code describing which texture target is enabled; it's just shader stuff. So they had to make a rule that says that two samplers cannot use the same unit if they're different types.

That's why each texture unit has multiple independent binding points: OpenGL's commitment to backwards compatibility.

It is best to ignore that this capability exists. Bind the right textures that your particular shader needs. So focus on using those functions, and don't worry about the fact that you could have two textures bound to the same target. If you want to make certain that you're not accidentally using the wrong texture, you can use glBindTextures or glBindTextureUnit with a texture name of 0, which will unbind all targets in the particular texture unit(s).

like image 167
Nicol Bolas Avatar answered Sep 18 '22 04:09

Nicol Bolas