Tutorial 4 – Depth
So far we’ve drawn a single polygon to the screen and it’s all looked exactly as we intended. But what happens when we start drawing more polygons.
First lets add a new object to our scene. Triangles are a bit dull now so here’s a quad made of a TriangleStrip!
glBegin(GL_QUADS); glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(-1.0f, -1.0f, 0.0f); glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(-0.8f, 1.0f, 0.0f); glColor3f(0.75f, 0.75f, 0.75f); glVertex3f(1.0f, 0.5f, -1.0f); glColor3f(0.75f, 0.75f, 0.75f); glVertex3f(0.6f, -0.9f, -1.0f); glEnd();
When we run this program this is what you should see:
Notice that no matter how much the scene is rotated, the quad always appears to be on top of the triangle. The reason for this is that we’re not testing the depth of each pixel before we draw it.
When you attempt to draw an object using a graphics API such as OpenGL, the commands get sent to your graphics card, the vertices are all arranged into 3D space and then projected into 2D screen-space. After this the hardware starts to fill in the gaps between the vertices (So far it’s been blending the red, green and blue colours in the pixels between our triangle’s vertices). In the simplest case the last object to be drawn will show up on screen. This is the reason why our triangle is always on top; The quad is actually being drawn correctly to the screen, but then the triangle is being drawn right over the top of it. What we need to do is tell the graphics hardware to check whether the fragment it is about to colour in is actually behind anything, if that’s the case then we obviously won’t draw it!
To tell the graphics card to do this is quite simple and fairly self explanatory. We simply turn on depth testing:
This is not all we need to do however. If you leave it at this you’ll be lucky if you see anything on screen at all! Remember the section of code that clears the colour buffer so that it is ready to be written to. The depth buffer works on the same principle. If it’s already full of uncleared values then our depth testing won’t work as expected. In order to fix this we change our “glClear” call to look like this:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Once you’ve done this you should have depth correctly enabled in your scene and should now be rendering something a little like this:
As you can see, now that we’ve added depth testing, the objects that are closer to the camera appear to be on top of those that are further away.