6

I am very new to the OpenGL API and just discovered textures and how to use them. The generated texture buffers are not bound in the same way as regular uniforms are bound and instead use glActiveTexture, followed by a bind rather than just supplying the texture to the shaders via glUniform as we do with other constants.

What is the reasoning behind this convention?

The only reason I can think of is to utilize the graphics card's full potential and texture processing capabilities instead of just binding buffers directly. Is this correct reasoning, or is it simply the way the API was implemented?

No reasoning is given on the official wiki, just says that it's weird: "Binding textures for use in OpenGL is a little weird" https://www.khronos.org/opengl/wiki/Texture

Timothy
  • 61
  • 2
  • 1
    [Related if not duplicate](https://stackoverflow.com/questions/45233643/opengl4-5-bind-multiple-textures-and-samplers/45240467#45240467) – Borgleader Aug 27 '17 at 15:12
  • I'll take a look to see if it answers my question, thanks. Didn't see that one. – Timothy Aug 27 '17 at 15:14
  • If you use "direct state access" (DSA) the API makes a lot more sense. Assuming you're using GL core 4.5 or later. – Robinson Aug 27 '17 at 20:46

2 Answers2

8

Your question can be interpreted in two ways.

"Why do we bind textures to the context rather than to the shader?"

Because that would make it needlessly difficult to have multiple shaders use the same textures. Note that pretty much no graphics API directly attaches the texture to the program. Not D3D of any version, not Metal, nor even Vulkan.

Textures are resources used by shaders. But they are not part of the shader.

"Why do we treat textures differently from a general array of values?"

In modern OpenGL, shaders have access to several different kinds of resources: UBOs, SSBOs, textures, and images. Each of these kinds of resources ultimately represents a potentially distinct part of the graphics hardware.

A storage block is not just a uniform block that can be bigger. Storage buffers represent the shader doing global memory accesses, while uniform blocks are often copied directly into the shader execution units. In the latter case, accessing their data is much faster, but that also means that you're limited by how much storage those execution units can have.

Now, this is not true for all hardware (AMD's GCN hardware treats the two almost identically, which is why their UBO limits are so large). But it is true of much hardware.

Textures are even more complicated, because implementations need to be able to store their data in an optimal way for performance reasons. As such, texture storage formats are opaque. They're even opaque in ostensibly low-level APIs like Vulkan. Oh sure, linear formats exist, but implementations aren't required to let you read from them at all.

So textures are not just constant arrays.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
1

You are comparing two completely different things

A texture object can (somehow) be compared to a buffer object. The texture is bound by a combination of glActiveTexture and glBindTexture to a texture unit, whereas a buffer is bound by glBindBuffer which is kind-off similar.

A texture sampler uniform is a uniform in the shader and should thus be compared with other uniforms. This sampler is set by a glUniform1i call.

BDL
  • 21,052
  • 22
  • 49
  • 55
  • So the sampler is what is set by the uniform calls and they get their texture data from the texture units. Got it. But, what is the reason behind doing it this way rather than just a giant array of pixel colors (the texture) sent to the shaders normally? Hardware benefits? – Timothy Aug 27 '17 at 15:22
  • @Timothy: "*But, what is the reason behind doing it this way rather than just a giant array of pixel colors (the texture) sent to the shaders normally?*" What do you mean by "normally"? There is no "normal" way to send a "giant array of pixel colors" to a shader. Most textures would easily blow past the storage limits of uniform arrays or even UBOs. – Nicol Bolas Aug 27 '17 at 15:23
  • @NicolBolas Large textures may blow past the limits, but smaller textures won't. So you're saying that the answer is simply storage size concerns? – Timothy Aug 27 '17 at 15:39
  • @Timothy: No, what I'm saying is that the question *makes no sense*. Textures are not uniform arrays, so it makes no sense to access textures the way you would a uniform. – Nicol Bolas Aug 27 '17 at 15:53