A detailed look at implementing graphically demanding games in OpenGL with Java, using the JOGL library

Tuesday, December 23, 2008

Texture mapping

Sooner or later everyone gets bored of plain coloured triangles. Texturing in OpenGL is easy enough once you've mastered a few concepts:
  • Texture names
  • Filtering
This post (and the accompanying source code) also builds slightly on the previous tutorial - the rendering we're interested in is now in TutorialObject.java. The Canvas object holds a list of all objects and calls each one to render itself.

Texture names are actually numbers. The numbers are generated by glGenTextures and returned into an array like so:
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
The numbers returned in textures[] are effectively handles to textures. At the moment, they are not attached to any data - they are not even declared as 1 or 2 dimensional. To attach actual data, we must bind the texture:
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
then we can load our image data in with
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, 32, 32, 0, GL.GL_RGB, GL.GL_BYTE, b);
Hang on a minute, where do those parameters come from? The full details are at the OpenGL man pages, but the key ones are the 32s and b. This means we are defining a 32 square texture, and the data defining it is in the buffer b. In this example, b is just full of random data, so the texture looks like disco lights.

If we tried to render a triangle now, it still wouldn't be textured. We need to enable texturing and choose a filtering mode. So at the beginning of our object rendering code, we make these calls:
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
Note that I re-bind the texture. This is because in a realistic program, different objects will need different textures and you won't know which texture is active at the beginning of an object's display method.
Now we can render vertices and expect to see our texture.

gl.glBegin(GL.GL_TRIANGLES);
{
gl.glTexCoord2f(0.0f,0.0f);
gl.glVertex3f(0.0f, 1.0f, -3.0f);

gl.glTexCoord2f(1.0f,0.0f);
gl.glVertex3f(-1.0f, -1.0f, -3.0f);

gl.glTexCoord2f(0.0f,1.0f);
gl.glVertex3f(1.0f, -1.0f, -3.0f);
}
gl.glEnd();
We need to pass the texture coordinates before the vertex coordinates - when a vertex is defined it picks up the last specified texture coordinates, color, normal etc.

No comments:

Post a Comment