Building a 3D Engine in Perl, Part 4
by Geoff Broadwell
|
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);
}

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).

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).

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).

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).

Figure 6. Position-independent frame rate
Prev [1] [2] [3] [4] [5] [6] [7] [8] Next