Next | Prev | Up | Top | Contents | Index

Working on a Geometry-Limited Program

Previous tests determined that the program is geometry-limited. The next step is therefore to pinpoint the most severe problems and to change the program to alleviate the bottleneck.

Since the purpose of the program is to draw a lighted sphere, you can't eliminate lighting altogether. The program is already using a fairly simple lighting model (a single infinite light and a nonlocal viewer), so there's not much performance to be gained by changing the lighting model.


Smooth Shading Versus Flat Shading

Smooth shading requires more computation than flat shading, so consider changing

glShadeModel(GL_SMOOTH);
to

glShadeModel(GL_FLAT);
This increases performance to about 2.75 frames per second. Since this isn't much better than 2.5 frames per second, this discussion continues to use smooth shading.


Reducing the Number of Polygons

Since a change in lighting and shading does not improve performance significantly, the best option is to reduce the number of polygons the program is drawing.

One approach is to tesselate the sphere more efficiently. The simple sphere model used in the program has very large numbers of very small quadrilaterals near the poles, and comparatively large quadrilaterals near the equator. Several superior models exist, but to keep things simple, this discussion continues to use the latitude/longitude tesselation.

A little experimentation shows that reducing the number of quadrilaterals in the sphere causes a dramatic performance increase. When the program places vertices every 10 degrees, instead of every degree, performance skyrockets to nearly 200 frames per second:

    for (latitude = -90; latitude < 90; latitude += 10) {
        glBegin(GL_QUAD_STRIP);
        for (longitude = 0; longitude <= 360; longitude += 10) {
             GLfloat x, y, z;
             x = sin(longitude * dToR) * cos(latitude * dToR);
             y = sin(latitude * dToR);
             z = cos(longitude * dToR) * cos(latitude * dToR);
             glNormal3f(x, y, z);
             glVertex3f(x, y, z);
             x = sin(longitude * dToR) * cos((latitude+10) * dToR);
             y = sin((latitude+10) * dToR);
             z = cos(longitude * dToR) * cos((latitude+10) * dToR);
             glNormal3f(x, y, z);
             glVertex3f(x, y, z);
             }
         glEnd()
         }
Of course, this yields a less smooth-looking sphere. When tuning, you often need to make such trade-offs between image quality and drawing performance, or provide controls in your application that allow end users to make the trade-offs.

In this particular case, the improvement up to 200 frames per second becomes apparent only because the program is single-buffered. If the program used double-buffering, performance wouldn't increase beyond the frame rate of the monitor (typically 60 or 72 frames per second), so there would be no performance penalty for using a higher-quality sphere.

If performance is truly critical and sphere intersections aren't likely, consider rendering more vertices at the edge of the silhouette and fewer at the center.


Next | Prev | Up | Top | Contents | Index