Recall that texture coordinates are defined
such that (0,0) is the lower-left corner and (1,1) is the upper-right
corner. So, what happens when a vertex has texture coordinates that lie
outside this range? The sample code is actually already sending
coordinates outside this range. For example, the
TextureCount parameter for the sphere is
(20,35).By default, OpenGL simply repeats the texture
at every integer boundary; it lops off the integer portion of the texture
coordinate before sampling the texel color. If you want to make this
behavior explicit, you can add something like this to the rendering engine
code:
glBindTexture(GL_TEXTURE_2D, m_gridTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
The wrap mode passed in to the third argument
of glTexParameteri can be one of the
following:
- GL_REPEAT
This is the default wrap mode; discard
the integer portion of the texture coordinate.
- GL_CLAMP_TO_EDGE
Select the texel that lies at the nearest
boundary.
- GL_MIRRORED_REPEAT
If the integer portion is an even number,
this acts exactly like GL_REPEAT. If it’s an odd
number, the fractional portion is inverted before it’s
applied.
Figure 1 shows the three
wrap modes. From left to right they’re repeat, clamp-to-edge, and
mirrored. The figure on the far right uses GL_REPEAT
for the S coordinate and GL_CLAMP_TO_EDGE for the T
coordinate.
What would you do if you wanted to animate your
texture coordinates? For example, say you want to gradually move the
grasshoppers in Figure 5-2 so that they scroll around
the Möbius strip. You certainly wouldn’t want to upload a new VBO at every
frame with updated texture coordinates; that would detrimental to
performance. Instead, you would set up a texture
matrix. The following snippet shows how you’d set up a texture
matrix with ES 1.1 (with ES 2.0, there’s no built-in texture matrix, but
it’s easy to create one with a uniform variable):
glMatrixMode(GL_TEXTURE);
glTranslatef(grasshopperOffset, 0, 0);
In this book, we use the convention that (0,0)
maps to the upper-left of the source image (Figure 5-3) and that the Y coordinate increases
downward.
Our texture coordinate convention is not what
you’d find in the OpenGL specification from Khronos, which proclaims
(0,0) to be the lower-left corner. However, the spec also says that when
uploading an image with glTexImage2D, it should be
arranged in memory such that the first row of data corresponds to the
bottom row in the image. In all of the methods we’re using to decode the
image, the top row of data comes first. |
By the way, saying that (1,1) maps to a texel
at the far corner of the texture image isn’t a very accurate statement;
the corner texel’s center is actually a fraction, as shown in Figure 2. This may seem pedantic, but you’ll see how
it’s relevant when we cover filtering, which comes next.