iPhone Game Development - Chris Craft [131]
glViewport(0, 0, backingWidth, backingHeight);
The following lines clear all transforms that may have been applied to the projection matrix:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
Next, you need to define a viewport. A viewport is not a camera, but a camera is probably the easiest way to think of it. A viewport is your window into the 3-D world. There are two types of viewports in OpenGL ES: You can define an orthogonal viewport or a frustum viewport. For this example, we use the orthogonal viewport. The following line of code defines the dimensions of the orthogonal viewport that we used for our viewing area.
An orthogonal viewport is the shape of a rectangle. This is not ideal for most 3-D environments because it does not produce a real-world perspective when rendered. However, this type of viewport works well for this example and for close-up views where perspective does not matter. If you need to render a larger area with objects deep in the background, you would want to switch to a frustum viewport. A frustum viewport is not shaped like an orthogonal viewport and it does produce real-world perspective when rendered.
The following line defines the orthogonal viewport:
glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
The following two lines switch to our model matrix mode and rotate:
glMatrixMode(GL_MODELVIEW);
glRotatef(3.0f, 0.0f, 0.0f, 1.0f);
The following lines replace all the pixels on the screen with gray:
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
The following lines load the vertices of our square. The first parameter tells OpenGL that we are using two dimensions assumed to cycle through X and Y, respectively:
glVertexPointer(2, GL_FLOAT, 0, squareVertices);
glEnableClientState(GL_VERTEX_ARRAY);
The next lines load the vertices' color definitions. The first parameter tells OpenGL that we are using four values per color assumed to cycle through red, green, blue, and alpha, respectively:
glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors);
glEnableClientState(GL_COLOR_ARRAY);
The next line draws the square with four vertices starting at index 0. The square is drawn to the render buffer:
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
The following lines tell the render buffer to bind to the context and in turn the frame buffer. This step triggers the objects in the render buffer to begin rasterizing. When complete, you will see your square on the screen:
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
Drawing a cube with volume
The next step is converting your OpenGL ES Application Template into an example that displays a 3-D cube with depth, color, and volume, as shown in Figure 9.17. You can download the full source for this example from http://appsamuckcom/opengl.
In the previous example, notice that the square is defined by defining the vertices that outline it. It's kind of like playing connect the dots. Defining a cube is the same as defining a square, with a couple of exceptions. First, you have to define six squares, one for each side. Second, you have to include X, Y, and Z coordinates instead of just X and Y. In the square example, you defined the array as follows:
const GLfloat squareVertices[] = {
-0.5f, -0.5f,
0.5f, -0.5f,
-0.5f, 0.5f,
0.5f, 0.5f,
};
FIGURE 9.17
A view of the 3-D cube rendered in this example with a different color on each face
Now the new definition that includes six sides and the additional Z coordinate looks like this:
const GLfloat cubeVertices[] = {
// Front Face
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
// Back Face
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
// Top Face
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
// Bottom Face
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, -0.5f,
// Left Face
-0.5f,