Sign In/My Account | View Cart  
advertisement


Listen Print Discuss

Building a 3D Engine in Perl, Part 4
by Geoff Broadwell | Pages: 1, 2, 3, 4, 5, 6, 7, 8

The first problem is reminiscent of the dark scene in the last article, after enabling lighting but no lights. Come to think of it, there's not much reason to have lighting enabled just to display stats, but the last object rendered by draw_view left it on. To make sure lighting is off, I added a set_lighting_2d routine, which draw_frame now calls just before calling draw_fps:

sub set_lighting_2d
{
    glDisable(GL_LIGHTING);
}

the unlit frame rate
Figure 2. The unlit frame rate

Figure 2 is much better! With lighting turned off, the frame rate now renders in bright white as intended. The next problem is the incorrect position. Moving and rotating the viewpoint shows that while the digits always face the screen, their apparent position moves around (Figure 3).

moving frame rate
Figure 3. A moving frame rate

It turns out that the current modelview and projection matrices transform the raster position set by glRasterPos, just like the coordinates from a glVertex call. That means OpenGL reuses whatever state the modelview and projection matrices are in.

To get unaltered window coordinates, I need to use an orthographic projection (no foreshortening or other non-linear effects) matching the window dimensions. I also need to set an identity modelview matrix (so that the modelview matrix won't transform the coordinates at all). All of this happens in set_projection_2d, called just before set_lighting_2d in draw_frame:

sub set_projection_2d
{
    my $self = shift;

    my $w    = $self->{conf}{width};
    my $h    = $self->{conf}{height};

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity;
    gluOrtho2D(0, $w, 0, $h);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity;
}

This routine first gathers the window width and height from the configuration hash. It then switches to the projection matrix (GL_PROJECTION) and restores the identity state before calling gluOrtho2D to create an orthographic projection matching the window dimensions. Finally, it switches back to the modelview matrix (GL_MODELVIEW) and restores its identity state as well. The frame rate now renders at the intended spot near the lower-left corner (Figure 4).

frame rate in the right spot
Figure 4. The frame rate in the correct position

There is another more subtle rendering problem, however, which you can see by moving the viewpoint forward a bit (Figure 5).

frame rate depth problems
Figure 5. Frame rate depth problems

Notice how the "5" is partially cut off. The problem is that OpenGL compares the depth of the pixels in the thin yellow box to the depth of the pixels in the frame rate display, and finds that some of the pixels in the 5 are farther away than the pixels in the box. In effect, part of the 5 draws inside the box. In fact, moving the viewpoint slightly to the left from this point will make the frame rate disappear altogether, hidden by the near face of the yellow box.

That's not very good behavior from a statistics display that should appear to hover in front of the scene. The solution is to turn off OpenGL's depth testing, using a new line at the end of set_projection_2d:

glDisable(GL_DEPTH_TEST);

With this change, you can move the view anywhere without fear that the frame rate will be cut off or disappear entirely (Figure 6).

position-independent frame rate
Figure 6. Position-independent frame rate

Pages: 1, 2, 3, 4, 5, 6, 7, 8

Next Pagearrow