Menu
OpenGL ES Tutorials

OpenGL ES

Depth



Tutorials > OpenGL ES > Depth

View Full Source

Introduction

Depth Up until now, any primitives that you displayed would appear on top of each other depending on the order that they were displayed in. This would occur, even if the primitives had different z values.

This tutorial will discuss how depth can be added to your programs, allowing the z coordinate to work correctly.

This is accomplished by using what is called a depth buffer. The depth buffer contains a value for every pixel on the screen. This value is in the range [0,1]. This represents the distance between the object and the viewer. Every coordinate has an associated depth value. When two depth values are compared, the lower of the two values will appear on the screen. A coordinate that is in front of another will have a lower depth value. You will see how this works further down in the tutorial.

Contents of main.cpp :


void init()
{

The first step that must be taken is to enable the depth buffer. This is done by passing the GL_DEPTH_TEST flag to the glEnable function.

For the depth buffer to be updated for writing, GL_TRUE needs to be passed to the glDepthMask function. This value is passed by default so we do not need to call the function. If you would like to disable writing to the depth buffer but you would still the buffer enabled, you can pass GL_FALSE onto this function.

	glEnable(GL_DEPTH_TEST);

At the beginning of the tutorial, we said that the lower the depth value, the closer the coordinate is to the viewer. This can be changed by using the glDepthFunc function. This function specifies how values in the depth buffer will be compared. The values that can be passed onto the function are given below :

Flag Description
GL_NEVER Never passes.
GL_LESS Passes if the incoming depth value is less than the stored value.
GL_EQUAL Passes if the incoming depth value is equal to the stored value.
GL_LEQUAL Passes if the incoming depth value is less than or equal to the stored value.
GL_GREATER Passes if the incoming depth value is greater than the stored value.
GL_NOTEQUAL Passes if the incoming depth value is not equal to the stored value.
GL_GEQUAL Passes if the incoming depth value is greater than or equal to the stored value.
GL_ALWAYS Always passes.

When drawing a primitive, the depth test will take place. If the test passes, the incoming color value will replace the current one.

The default value is GL_LESS. We want the test to pass if the values are equal as well. This will cause objects with the same z value. to display depending on the order that they were drawn in. We therefore pass GL_LEQUAL to the function.

	glDepthFunc(GL_LEQUAL);

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

For depth testing to be able to compare values, you need to initialize all values in the buffer. This can be achieved by using the glClearDepthf function. This function takes one parameter which specifies what the values in the depth buffer should be initialized with. We pass 1 to the function as this will allow any primitive to appear on the screen. If you had chosen a comparison function of GL_GREATER or GL_GEQUAL, you would have needed to pass 0 to this function.

	glClearDepthf(1.0f);

We are going to be displaying some triangles onscreen to show how the depth buffer works.

	glVertexPointer(3, GL_FLOAT, 0, triangle);
	glColorPointer(4, GL_FLOAT, 0, colors);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);
}

void display()
{

As with the color buffer, a call to glClear needs to be made to clear the depth buffer with the value passed to glClearDepth. GL_DEPTH_BUFFER_BIT must be passed onto the glClear function to achieve this. This can be done at the same time as the color buffer by separating the flags with an | (or) symbol.

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

We draw our first triangle, centered in the screen.

	glDrawArrays(GL_TRIANGLES, 0, 3);

The second triangle behind and slightly to the left of the first triangle.

	glPushMatrix();
	{
		glTranslatef(-0.2f, 0.0f, -1.0f);

		glDrawArrays(GL_TRIANGLES, 0, 3);

The third triangle is rotated 45 degrees and is at the same distance in the z axis as the second triangle.

		glRotatef(45.0f, 0.0f, 0.0f, 1.0f);

		glDrawArrays(GL_TRIANGLES, 0, 3);
	}
	glPopMatrix();

The last triangle is placed in the same z axis position as the first triangle. This is the small triangle that lies to the right.

	glPushMatrix();
	{
		glTranslatef(0.5f, 0.0f, 0.0f);
		glScalef(0.5f, 0.5f, 0.5f);

		glDrawArrays(GL_TRIANGLES, 0, 3);
	}
	glPopMatrix();

	glFlush();
	glutSwapBuffers();
}

Our menu code has changed slightly. A new function, glIsEnabled, is given below. This function takes one flag and determines if it enabled. You can pass any parameter that is usually passed onto the glEnable and glDisable functions. The code below allows you to select the depth menu option to enable and disable depth testing.

void menu(int entry)
{
	switch(entry)
	{
	case 1 : exit(0); break;
	case 2 :
		if (glIsEnabled(GL_DEPTH_TEST))
			glDisable(GL_DEPTH_TEST);
		else
			glEnable(GL_DEPTH_TEST);
		
		glutPostRedisplay();
		break;
	}
}

The glutInitDisplayMode / ugCreateWindow can be used to enable certain buffers. For the depth buffer to work with the UG library, the UG_DEPTH flag needs to passed as the second parameter of the ugCreateWindow function. With GLUT|ES, you need to simply pass the GLUT_DEPTH flag onto the glutInitDisplayMode function as shown below. This allocates memory for the depth buffer.

	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

Running the program, you will notice that the second and third triangles both appear behind the first triangle. This is because they are at a more negative z axis position.

The fourth triangle is in front of the first triangle as it was drawn afterwards. The third triangle appears in front of the second triangle for the same reason.

Turning off depth testing by selecting the depth menu option will result in the triangles overlapping depending on the order that they were drawn in. The first triangle is at the back and the last triangle is shown in the front.

Please let me know of any comments you may have : Contact Me

GLUT|ES Source Files : Embedded Visual C++ 4.0
UG Source Files : Embedded Visual C++ 4.0

Last Updated : 20 November 2005


< Tutorial 10 - Transformations Tutorial 12 - Perspective >

Back to Top


All Rights Reserved, © Zeus Communication, Multimedia & Development 2004-2005

Read the Disclaimer

Links