# OpenGL:Tutorials:Tutorial Framework:Adding Depth and Color

An illusion of depth is required in our application to provide the effect of a 3D world on a 2D screen. If we just rendered our polygons to the screen, they would overlap in draw order and look pretty naff.

## Setting up the Z-Buffer

The use of a Z-Buffer ensures that polygons overlap correctly. To enable the Z-Buffer within OpenGL we do two things:

```glEnable(GL_DEPTH_TEST);

Enabling the depth test makes every drawing operation check the Z-buffer before placing pixels onto the screen.
Enabling the depth mask makes every successful drawing operation place it's depth values into the Z-buffer.

Another technique that aids the illusion is backface culling. This works best with convex objects (cubes, spheres, etc). The method uses the normal vector of a polygon to determine its 'direction', only polygons that face the screen are drawn. In a cube, the three faces on the far side are not rendered, so they can't interfere with illusion of a soild object. Backface culling also reduces the on screen polycount by around a half, so it is a valuable optimisation.

Enabling backface culling in OpenGL is simple:

`glEnable(GL_CULL_FACE);`

We can change the behaviour of the culling with glCullFace() if required. Depending on the order in which your vertices are specified you can pass either GL_FRONT or GL_BACK:

```glCullFace(GL_FRONT);
// or
glCullFace(GL_BACK);```

In this example we're going to render a nice spinning cube, we'll color the faces to demonstrate OpenGL's color functions.

```  glBegin(GL_QUADS);
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);

glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glEnd();```

glColor() comes in a few flavours, the one used here specifies three float values in the range 0.0 - 1.0 for red, green and blue. Other versions of the function take integer or double arguments and specify alpha values too. The color specified is used for all drawing operations after the function call.

Having drawn the top and bottom faces for our cube, we now move onto the sides.

```     // Draw the side faces
glBegin(GL_TRIANGLE_STRIP);
glColor3f(1.0f,1.0f,1.0f); // White
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,0.0f); // Yellow
glVertex3f( 1.0f, 1.0f,-1.0f);
glColor3f(0.0f,1.0f,1.0f); // Aqua?
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(0.6f,0.6f,0.6f); // Gray
glVertex3f(-1.0f, 1.0f,-1.0f);
glColor3f(0.1f,0.1f,0.1f); // Dark Gray
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f, 1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f); // Red
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd();```

The triangle strip drawing method treats the first three vertices as a triangle, subsequent vertices produce a new triangle using the previous two points.
We specify a new color for each vertex, the result is a smooth transition between the colors rather than the flat color produced on the quads.

Pressing the 'W' key during the program displays a wireframe view to illustrate how the triangle strip is created.

Try commenting out the Z-Buffer and backface culling commands to see how the illusion is destroyed when the polygons are not displayed correctly.

## Source Code

The source to Render.cpp, compile this demo using the OpenGL Tutorial Framework

```#include "Framework.h"

void Render(void)
{
float Rotate=0.0f; // A rotation value to be used to spin our polygon

glClearColor(0,0,0,0);

// Setup our screen
glViewport(0,0,800,600);
glMatrixMode(GL_PROJECTION);
gluPerspective(45.0f,800.0f/600.0f,1.0f,500.0f);
glMatrixMode(GL_MODELVIEW);

// Ensure correct display of polygons
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);

// This loop will run until Esc is pressed
while(RunLevel)
{
if(Keys[VK_ESCAPE]) // Esc Key
RunLevel=0;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear screen and z-buffer
glLoadIdentity(); // Reset current matrix (Modelview)

// Press 'w' to show wireframe view
if(Keys['W'])
glPolygonMode(GL_FRONT,GL_LINE);
else
glPolygonMode(GL_FRONT,GL_FILL);

// Do our rotations
glTranslatef(0.0f,0.0f,-5.0f);
glRotatef(Rotate,0.0f,0.0f,1.0f);
glRotatef(Rotate,1.0f,0.6f,0.0f);

// Draw the top and bottom faces
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);

glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glEnd();

// Draw the side faces
glBegin(GL_TRIANGLE_STRIP);
glColor3f(1.0f,1.0f,1.0f); // White
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,0.0f); // Yellow
glVertex3f( 1.0f, 1.0f,-1.0f);
glColor3f(0.0f,1.0f,1.0f); // Aqua?
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(0.6f,0.6f,0.6f); // Gray
glVertex3f(-1.0f, 1.0f,-1.0f);
glColor3f(0.1f,0.1f,0.1f); // Dark Gray
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f, 1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f); // Red
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd();

// Add to the rotation for next frame
Rotate+=0.05f;

// Show our cube
FlipBuffers();
}

}```