Rendering the Scene

As we saw in Section 4.2, Drawing the Board, on page 83, the Android 2D library calls the onDraw( ) method of your view whenever it needs to redraw a section of the screen. OpenGL is a bit different.

In OpenGL ES on Android, drawing is separated into a rendering class that is responsible for initializing and drawing the entire screen. Let's define that now.

Here's the outline for the GLRenderer class:

Download OpenGL/src/org/example/opengl/

package org.example.opengl;

import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10;

import android.content.Context; import android.opengl.GLSurfaceView; import android.opengl.GLU; import android.util.Log;

class GLRenderer implements GLSurfaceView.Renderer { private static final String TAG = "GLRenderer"; private final Context context;

GLRenderer(Context context) { this.context = context;

public void onSurfaceCreated(GL10 gl, EGLConfig config) { // ...

public void onSurfaceChanged(GL10 gl, int width, int height) {

public void onDrawFrame(GL10 gl) {

Line 1 2

GLRenderer implements the GLSurfaceView.Renderer interface, which has three methods. Let's start with the onSurfaceCreated() method, which is called when the OpenGL Surface (kind of like a Canvas in regular 2D) is created or re-created:

Download OpenGL/src/org/example/opengl/

public void onSurfaceCreated(GL10 gl, EGLConfig config) { // Set up any OpenGL options we need gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

// Optional: disable dither to boost performance // gl.glDisable(GL10.GL_DITHER);

On line 3, we set a couple of OpenGL options. OpenGL has dozens of options that can be enabled or disabled with glEnable( ) and glDisable( ). The most commonly used ones include the following:

Option Description

GL_BLEND Blend the incoming color values with the values already in the color buffer. GL_CULL_FACE Ignore polygons based on their winding (clockwise or counterclockwise) in window coordinates. This is a cheap way to eliminate back faces. GL_DEPTH_TEST Do depth comparisons, and update the depth buffer. Pixels farther away than those already drawn will be ignored. GL_LIGHTi Include light number i when figuring out an object's brightness and color. GL_LIGHTING Turn on lighting and material calculations.

GL_LINE_SMOOTH Draw antialiased lines (lines without jaggies). GL_MULTISAMPLE Perform multisampling for antialiasing and other effects.

GL_POINT_SMOOTH Draw antialiased points. GL_TEXTURE_2D Use textures to draw surfaces.

All options are off by default except for GL_DITHER and GL_MULTISAMPLE. Note that everything you enable has some cost in performance.

Next let's fill out the onSurfaceChanged( ) method. This method is called once after the Surface is created and then again whenever the size of the Surface changes:

Download OpenGL/src/org/example/opengl/

Line 1 public void onSurfaceChanged(GL10 gl, int width, int height) {

2 // Define the view frustum

3 gl.glViewport(0, 0, width, height);

4 gl.glMatrixMode(GL10.GL_PROJECTION);

5 gl.glLoadIdentity();

7 GLU.gluPerspective(gl, 45.0f, ratio, 1, 100f);

Here we configure our view frustum and set a few OpenGL options. Note the call to the GLU.gluPerspective() helper function on line 7. The last two arguments are the distance from the eye to the near and far clipping planes (see Figure 10.1, on page 199).


Figure 10.2: That was a lot of trouble to get a black screen.

It's time to draw something. The onDrawFrame() method is called over and over in the rendering thread created by the GLSurfaceView class.

Download OpenGL/src/org/example/opengl/

public void onDrawFrame(GL10 gl) { // Clear the screen to black gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

// Position model so we can see it gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0, 0, -3.0f);

// Other drawing commands go here...

To start with, we set the screen to black. We clear both the color and depth buffers. Always remember to clear both, or you'll get some very

Version l.what?

OpenGL ES 1.0 is based on full OpenGL version 1.3, and ES 1.1 is based on OpenGL 1.5. JSR 239 has two versions: the original 1.0 and a maintenance release version 1.0.1. There are also some OpenGL ES extensions that I won't get into. All versions of Android implement JSR 239 1.0.1, with OpenGL ES 1.0 and some 1.1. For most programs, the JSR standard will suffice, so that's what we use in this chapter.

Starting with Android 2.2, OpenGL ES 2.0 is supported via the android.opengl package.* You can also call it from the Native Development Kit (NDK).f OpenGL ES 2.0 is defined relative to the full OpenGL 2.0 specification and emphasizes shaders and programmable 3D pipelines. There is no JSR standard yet for OpenGL ES 2.0, and the programming interface is not backwards compatible with 1.0.

*. f.

strange results left over from the depth information for the previous frame. We also set the starting position for the rest of the drawing commands, which will be completed in the next section.

If you run the program now, you get Figure 10.2, on the previous page. If you're thinking that it's silly to draw the same black screen over and over again in a loop, you're right. This will make more sense later when we talk about animation, so just bear with me for now.

Let's move on and draw something a little more interesting. But first we need to define exactly what we're drawing (the model).

0 0

Post a comment