开发者

What's the difference between glClient*** gl***?

I'm learning GLES. There are 开发者_Python百科many pair functions like glClientActiveTexture/glActiveTexture. What's the difference between them? (Especially the case of glClientActiveTexture)


From the openGL documentation:

  • glActiveTexture glActiveTexture selects which texture unit subsequent texture state calls will affect.
  • glClientActiveTexture selects the vertex array client state parameters to be modified by glTexCoordPointer.

On one hand, glClientActiveTexture is used to control subsequent glTexCoordPointer calls (with vertex arrays). On the other hand glActiveTexture affects subsequent calls to glTexCoord calls (used by display lists or immediate mode (non existent in OpenGL ES (AFAIK)).


Adding to Kenji's answer, here's a bit more detail (and bearing in mind that not everything in OpenGL is available in ES).

Terminology

But first some quick terminology to try to prevent confusion between all the texturish things (oversimplified for the same reason).

  • Texture Unit: A set of texture targets (e.g. GL_TEXTURE_2D). It is activated via glActiveTexture
  • Texture Target: A binding point for a texture. It specifies a type of texture (e.g. 2D). It is set via glBindTexture.
  • Texture: A thing containing texels (image data, e.g. pixels) and parameters (e.g. wrap and filter mode) that comprise a texture image. It is identified by a key/name/ID, a new one of which you get via glGenTextures, and it is actually instantiated via (first call to) glBindTexture with its name.

Summary: A texture unit has texture targets that are bound to textures.

Texture Unit Activation

In order to have multitexturing with 2D textures (for example), wherein more than one 2D texture must be bound simultaneously for the draw, you use different texture units - bind one texture on one unit's 2D target, and bind the next on another unit's 2D target. glActiveTexture is used to specify which texture unit the subsequent call to glBindTexture will apply to, and glBindTexture is used to specify which texture is bound to which target on the active texture unit.

Since you have multiple textures, you're likely to also have multiple texcoords. Therefore you need some way to communicate to OpenGL/GLSL that one set of texcoords is for one texture/unit, and another set of texcoords is for another. Usually you can do this by just having multiple texcoord attributes in your vertex and corresponding shader. If you're using older rendering techniques that rely on pre-defined vertex attributes in the shader, then you have to do something different, which is where glClientActiveTexture comes in. The confusion happens because it takes an argument for a texture unit, but it does not have the same implications as glActiveTexture of activating a texture unit in the state machine, but rather it designates which pre-defined gl_MultiTexCoord attribute (in the shader) will source the texcoords described in the subsequent call to glTexCoordPointer.

In a nutshell, glActiveTexture is for texture changes, and glClientActiveTexture is for texcoord changes. Which API calls you use depends on which rendering technique you use:

  • glActiveTexture sets which texture unit will be affected by subsequent context state calls, such as glBindTexture. It does not affect glMultiTexCoord, glTexCoord, or glTexCoordPointer, because those have to do with texcoords, not textures.
  • glClientActiveTexture sets which texture unit subsequent vertex array state calls apply to, such as glTexCoordPointer. It does not affect glBindTexture, because that has to do with textures, not texcoords.
    • It also does not affect glMultiTexCoord which uses DSA to select a texture unit via its target parameter, nor does it affect glTexCoord, which targets texture unit 0 (GL_TEXTURE0). This pretty much just leaves glTexCoordPointer as the thing it affects, and glTexCoordPointer is deprecated in favor of glVertexAttribPointer, which doesn't need glClientActiveTexture. As you can see, glClientActiveTexture isn't the most useful, and is thusly deprecated along with the related glWhateverPointer calls.
  • You'll use glActiveTexture + glBindTexture with all techniques to bind each texture on a specific texture unit. You'll additionally use glClientActiveTexture + glTexCoordPointer when you're using DrawArrays/DrawElements without glVertexAttribPointer.

Multitexturing Examples

As OpenGL has evolved over the years, there are many ways in which to implement multitextured draws. Here are some of the most common:

  1. Use immediate mode (glBegin/glEnd pairs) with GLSL shaders targeted for version 130 or older, and use glMultiTexCoord calls to specify the texcoords.
  2. Use glBindVertexArray and glBindBuffer + glDrawArrays/glDrawElements to specify vertex data, and calls to glVertexPointer, glNormalPointer, glTexCoordPointer, etc., to specify vertex attributes during the draw routine.
  3. Use glBindVertexArray + glDrawArrays/glDrawElements to specify vertex data, with calls to glVertexAttribPointer to specify vertex attributes during the init routine.

Here are some examples of the API flow for multitexturing with two 2D textures using each of these techniques (trimmed for brevity):

  1. Using immediate mode:

    • init
    • draw
    • shutdown
    • vertex shader
    • fragment shader
  2. Using DrawElements but not VertexAttribPointer:

    • init
    • draw
    • shutdown
    • vertex shader (same as immediate mode)
    • fragment shader (same as immediate mode)
  3. Using DrawElements and VertexAttribPointer:

    • init
    • draw
    • shutdown
    • vertex shader
    • fragment shader

Misc. Notes

  • glMultiTexCoord populates unused coords as 0,0,0,1. e.g. glMultiTexCoord2f == s,t,0,1
  • Always use GL_TEXTURE0 + i, not just i.
  • When using GL_TEXTURE0 + i, i must be within 0 - GL_MAX_TEXTURE_COORDS-1.
  • GL_MAX_TEXTURE_COORDS is implementation-dependent, but must be at least two, and is at least 80 as of OpenGL 4.0.
  • glMultiTexCoord is supported on OpenGL 1.3+, or with ARB_multitexture
  • Do not call glActiveTexture or glBindTexture between glBegin and glEnd. Rather, bind all needed textures to all needed texture units before the draw call.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜