Software, Hardware, Research – Results

This is the first in what I hope to be a couple of examples on using OpenGL on the iPhone. As we all know, there are examples around, but not that many. Jeff LaMarche is porting some of the NeHe tutorial examples, which is great.

I know that OpenGL ES 1.1 is what’s in use on the iPhone, but have been working my way through the OpenGL ES 2.0 Programming Guide anyway, trying to make things work.

To make a long story short, I started by wanting to do some water effects alá Koi Pond and ended up looking at multi-texturing. After some thrashing around, the solution is really straightforward. The main “mental” hurdle (in my case) was to remember that OpenGL implementations are state machines. You set the state and then execute the rendering.

What we’re going for in this example is what is shown on page 223 of the OpenGL ES 2.0 Programming Guide, namely one texture (brick wall) modulated by another (a light map). The effect is that of a light shining on a wall.

To make this simple, I’ve based this example on the PVRTextureLoader example from Apple, which you need to get and, if you are going to run the example on a device, configure for your registered device(s). We’ll stick with the brick texture that comes with it, but will need a light map for the modulation. For that you can download the OpenGL ES 2.0 Programming Guide sources and grab the image, or just use the image below.

The inspiration for the multi-texturing was taken from the Oolong engine Per-PixelLighting example (Oolong Engine2/Examples/Renderer/). All the code changes required are made in the EAGLView.h and EAGLView.m files.

The light map is a second texture, so we need to define an index for it to be used in the GLuint _textures[kNumTextures] array. Near the top of EAGLView.h, add the enum indicated below.

/* Use the current texture as source 1 */ glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);

/* Set what we will operate on, in this case we are going to use just the texture colours. */ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);

I’ve added extra comments to help understand the changes. The only other thing worth noting is the glTexParameteri statements applied to the light map texture. Since the glBindTexture call for the light map is fixed, we could have moved these outside the drawView method and saved some cycles. However, I put them in as the germ of a “reader exercise” to add mipmap support for the light map. When you try the demo controls, you’ll see what I mean ;-)

The final result should look like the screenshot below.

After this, I’ll be playing with normals. I’ve managed to create a faux distortion effect by shifting texture vertices, so the next step is to look at lighting and surface effects...