We can let a sampler2D
in GLSL associate with a texture unit explicitly:
layout(binding = 0) uniform sampler2D sampler;
Is there another way through which that I can assign a binding value to a sampler2D
in C code? Can I do like this?
//binding sampler to texture unit 1
glUniform1i(glGetUniformLocation(program, "sampler"), 1);
GLSL was not designed with all of its features in one go. It gradually accrued features over time, with no major revision rethinking how they all interact. That has led to some confused terminology as the language evolved.
In the initial design for GLSL, there was only one kind of external resource shaders could directly access: samplers. And it conceptually only had one useful datum: the texture image unit that it would look for an image of that type. And since such bindings couldn't be changed within a rendering command, it made sense to declare these to be "uniforms". And therefore, the uniform interface was used to set them.
That is, the "value" of a sampler is the texture image unit index for the texture it represents. As such, you can set this "value" using the same function you use to set any other uniform's value: gl(Program)Uniform*
.
But then GLSL needed to add a new kind of resource: uniform buffer objects.
Since UBOs are a way to provide uniform data, it would be really confusing to call a uniform block a "uniform". Therefore, it couldn't overload the gl(Program)Uniform*
API to set its binding index.
So they made a dedicated function to do it.
Fast-forward to GLSL 4.20. It has always made sense to declare the binding index for resources within the shader itself, but it wasn't until 4.20 that this was actually put into the API. On a conceptual level, a UBO and a texture are the same kind of thing: an external resource accessible through a shader. As such, when it came time to specify the indices in the shader, it used the same terminology for the interface: binding = X
.
They could have preserved the notion of samplers (and other opaque types) having a "value" that is their index. So setting the binding in the shader would look like uniform sampler2d variable = index;
. But the language designers (who, BTW, were not the people who initially designed what would become the OpenGL shading language) preferred to have a more uniform look to them.
So from the API perspective, they look like two different interfaces. But from the shader, they are the same kind of thing.