OpenGL ES 3 (iOS) texturing oddness - want to know why

我们两清 提交于 2019-12-13 02:16:12

问题


I have a functioning OpenGL ES 3 program (iOS), but I've having a difficult time understanding OpenGL textures. I'm trying to render several quads to the screen, all with different textures. The textures are all 256 color images with a sperate palette.

This is C++ code that sends the textures to the shaders

    // THIS CODE WORKS, BUT I'M NOT SURE WHY
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, _renderQueue[idx]->TextureId);
    glUniform1i(_glShaderTexture, 1);  // what does the 1 mean here

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, _renderQueue[idx]->PaletteId);
    glUniform1i(_glShaderPalette, 2);  // what does the 2 mean here?

    glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);

This is the fragment shader

uniform sampler2D texture; // New
uniform sampler2D palette;                     // A palette of 256 colors
varying highp vec2 texCoordOut;
void main()
{
    highp vec4 palIndex = texture2D(texture, texCoordOut);    
    gl_FragColor = texture2D(palette, palIndex.xy);
}

As I said, the code works, but I'm unsure WHY it works. Several seemingly minor changes break it. For example, using GL_TEXTURE0, and GL_TEXTURE1 in the C++ code breaks it. Changing the numbers in glUniform1i to 0, and 1 break it. I'm guessing I do not understand something about texturing in OpenGL 3+ (maybe Texture Units???), but need some guidance to figure out what.


回答1:


Since it's often confusing to newer OpenGL programmers, I'll try to explain the concept of texture units on a very basic level. It's not a complex concept once you pick up on the terminology.

The whole thing is motivated by offering the possibility of sampling multiple textures in shaders. Since OpenGL traditionally operates on objects that are bound with glBind*() calls, this means that an option to bind multiple textures is needed. Therefore, the concept of having one bound texture was extended to having a table of bound textures. What OpenGL calls a texture unit is an entry in this table, designated by an index.

If you wanted to describe this state in a C/C++ style notation, you could define the table of bound texture as an array of texture ids, where the size is the maximum number of bound textures supported by the implementation (queried with glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, ...)):

GLuint BoundTextureIds[MAX_TEXTURE_UNITS];

If you bind a texture, it gets bound to the currently active texture unit. This means that the last call to glActiveTexture() determines which entry in the table of bound textures is modified. In a typical call sequence, which binds a texture to texture unit i:

glActiveTexture(GL_TEXTUREi);
glBindTexture(GL_TEXTURE_2D, texId);

this would correspond to modifying our imaginary data structure by:

BoundTextureIds[i] = texId;

That covers the setup. Now, the shaders can access all the textures in this table. Variables of type sampler2D are used to access textures in the GLSL code. To determine which texture each sampler2D variable accesses, we need to specify which table entry each one uses. This is done by setting the uniform value to the table index:

glUniform1i(samplerLoc, i);

specifies that the sampler uniform at location samplerLoc reads from table entry i, meaning that it samples the texture with id BoundTextureIds[i].

In the specific case of the question, the first texture was bound to texture unit 1 because glActiveTexture(GL_TEXTURE1) was called before glBindTexture(). To access this texture from the shader, the shader uniform needs to be set to 1 as well. Same thing for the second texture, with texture unit 2.

(The description above was slightly simplified because it did not take into account different texture targets. In reality, textures with different targets, e.g. GL_TEXTURE_2D and GL_TEXTURE_3D, can be bound to the same texture unit.)




回答2:


GL_TEXTURE1 and GL_TEXTURE2 refer to texture units. glUniform1i takes a texture unit id for the second argument for samplers. This is why they are 1 and 2.

From the OpenGL website:

The value of a sampler uniform in a program is not a texture object, but a texture image unit index. So you set the texture unit index for each sampler in a program.



来源:https://stackoverflow.com/questions/27261380/opengl-es-3-ios-texturing-oddness-want-to-know-why

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!