To map a bitmap to a triangle we need to add so-called texture coordinates to each vertex of the triangle. What is a texture coordinate? It specifies a point within the texture (our uploaded bitmap) to be mapped to one of the triangle's vertices. Texture coordinates are usually 2D.
While we call our positional coordinates x, y, and z, texture coordinates are usually called u and v or s and t, depending on the circle of graphics programmers you are a part of. OpenGL ES calls them s and t, so that's what we'll stick to. If you read resources on the Web that use the u/v nomenclature, don't get confused: it's the same as s and t. So what does the coordinate system look like? Figure 7-10 shows Bob in the texture coordinate system after we uploaded him to OpenGL ES.
There are a couple of interesting things going on here. First of all, s equals the x-coordinate in a standard coordinate system, and t is equal to the y-coordinate. The s-axis points to the right, and the t-axis points downward. The origin of the coordinate system coincides with the top-left corner of Bob's image. The bottom-right corner of the image maps to (1,1).
So, what happened to pixel coordinates? It turns out that OpenGL ES doesn't like them a lot. Instead, any image we upload, no matter its width and height in pixels, will be embedded into this coordinate system. The top-left corner of the image will always be at (0,0), the bottom-right corner will always be at (1,1)â€”even if, say, the width is twice as large as the height. We call these normalized coordinates, and they actually makes our lives easier at times. So how can we map Bob to our triangle? Easy, we just give each vertex of the triangle a texture coordinate pair in Bob's coordinate system. Figure 7-11 shows a few configurations.
We can map our triangle's vertices to the texture coordinate system however we want. Note that the orientation of the triangle in the positional coordinate system does not have to be the same as in the texture coordinate system. The coordinate systems are completely decoupled. So let's see how we can add those texture coordinates to our vertices:
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(3 * VERTEX_SIZE); byteBuffer.order(ByteOrder.nativeOrder()); vertices = byteBuffer.asFloatBuffer(); vertices.put( new float[] { 0.0f, 0.0f, 0.0f, 1.0f,
319.0f, 0.0f, 1.0f, 1.0f, 160.0f, 479.0f, 0.5f, 0.0f});
vertices.flip();
That was easy. All we have to do is to make sure that we have enough room in our buffer, and then append the texture coordinates to each vertex. The preceding code corresponds to the rightmost mapping in Figure 7-10. Note that our vertex positions are still given in the usual coordinate system we defined via our projection. If we wanted to, we could also add the color attributes to each vertex, as in the previous example. OpenGL ES would then mix the interpolated vertex colors with the colors from the pixels of the texture that the triangle maps to on the fly. Of course, we'd need to adjust the size of our buffer, as well as the VERTEX_SIZE constant, accordingly (e.g., (2 + 4 + 2) x 4). To tell OpenGL ES that our vertices have texture coordinates, we again use glEnableClientState() together with the glTexCoordPointer()method, which behaves exactly the same as glVertexPointer() and glColorPointer() (can you see a pattern here?).
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
vertices.position(0);
gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices); vertices.position(2);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices);
Nice, that looks very familiar. So, the remaining question is how we can upload the texture to OpenGL ES and tell it to map it to our triangle. Naturally that's a little bit more involved. But fear not, it's still pretty easy.
Was this article helpful?