Depth Buffer Issue: Rendering Background Last Whites Out Other Textures

Hello! I’m fairly new to OpenGL and experimenting with various aspects of it. Right now, I am simply experimenting with rendering a handful of textured quads and the legendary teapot. However, I noticed that, depending on the order in which the various entities were being rendered, I received undesired results. Here are a few quick screenshots to demonstrate the problem. Clearly, even if the background is being rendered last, the Z-buffer should be sorting it properly regardless of render order. However, that is not happening, and it leads me to believe I have flubbed somewhere.

With Background - Rendered Last

No Background

I’m currently using SFML to assist with a few minor things so that I can focus on specific aspects at the moment.

Here is the InitRendering() function which is called shortly after boot-up. It creates the SFML window and handles general OpenGL setup and image loading.


bool InitRendering()
{
	// Create the main window
	gp_app = new sf::Window( sf::VideoMode(400, 400, 32), "SFML OpenGL" );
	cam_pos = RsdVector3( 0.0f, 0.0f, 0.0f );

	// Set color and depth clear value
	glClearColor(0.7f, 0.9f, 1.0f, 1.0f);

    // Enable Z-buffer read and write
    glEnable(GL_DEPTH_TEST);
	glClearDepth(1.0f);
	glDepthMask(GL_TRUE);
	glDepthFunc(GL_LEQUAL);
	glDepthRange(0.0f, 1.0f);

	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Set the blend function
    glDepthMask(GL_TRUE);

    // Setup a perspective projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.f, 1.f, 1.f, 500.f);

	/// Load and Store Textures
	glEnable( GL_TEXTURE_2D );
	const sf::Uint8* p_pixels;

	/// Teapot Texture
	sf::Image img2;
	img2.LoadFromFile( "assets/texture/test/checkerboard.png" );

	glGenTextures( 1, &teapot_texture_id );
	glBindTexture( GL_TEXTURE_2D, teapot_texture_id );

	p_pixels = img2.GetPixelsPtr();
	glTexImage2D(	GL_TEXTURE_2D, 
					0, 
					GL_RGBA, 
					img2.GetWidth(),
					img2.GetHeight(),
					0,
					GL_RGBA, 
					GL_UNSIGNED_BYTE,
					p_pixels );
	
	
	/// Plane Texture
	sf::Image img3;
	img3.LoadFromFile( "assets/texture/test/Plane_XZ.png" );

	glGenTextures( 1, &plane_texture_id );
	glBindTexture( GL_TEXTURE_2D, plane_texture_id );

	p_pixels = img3.GetPixelsPtr();
	glTexImage2D(	GL_TEXTURE_2D, 
					0, 
					GL_RGBA, 
					img3.GetWidth(),
					img3.GetHeight(),
					0,
					GL_RGBA, 
					GL_UNSIGNED_BYTE,
					p_pixels );

	/// BG Texture
	sf::Image img4;
	img4.LoadFromFile( "assets/texture/test/StarryBackground.png" );

	glGenTextures( 1, &bg_texture_id );
	glBindTexture( GL_TEXTURE_2D, bg_texture_id );

	p_pixels = img4.GetPixelsPtr();
	glTexImage2D(	GL_TEXTURE_2D, 
					0, 
					GL_RGBA, 
					img4.GetWidth(),
					img4.GetHeight(),
					0,
					GL_RGBA, 
					GL_UNSIGNED_BYTE,
					p_pixels );

	return true;
}

And this is the RenderScene() function which is called each pass. For the NoBackground screenshot, I simply commented out the code section labelled “///BG Texture”. The glutSolidTeapot function is copy-pasted from GLUT, so GLUT is not actually being used in my code.


void RenderScene()
{
	// Set the active window before using OpenGL commands
    // It's useless here because active window is always the same,
    // but don't forget it if you use multiple windows or controls
    gp_app->SetActive();

	// Clear color and depth buffer
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	/// Set Rendering Options
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	/// Switch to Model View mode
	glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();

	/// Apply some transformations
	glTranslatef( 0.0f, 0.0f, -20.0f );
	glTranslatef( -cam_pos.x, -cam_pos.y, -cam_pos.z );

	/// Plane Texture
	glBindTexture( GL_TEXTURE_2D, plane_texture_id );
    glBegin(GL_QUADS);
		glTexCoord2f( 0.0f, 0.0f );
		glVertex3f( -10.f, 0.0f, -10.0f );
		glTexCoord2f( 1.0f, 0.0f );
		glVertex3f( 10.0f,  0.0f, -10.0f);
		glTexCoord2f( 1.0f, 1.0f );
		glVertex3f( 10.f, 0.0f, 10.0f );
		glTexCoord2f( 0.0f, 1.0f );
		glVertex3f( -10.f, 0.0f, 10.0f );
	glEnd();

	/// Teapot
	glBindTexture( GL_TEXTURE_2D, teapot_texture_id );
	glFrontFace( GL_CW );
	glutSolidTeapot( 10.0f );
	glFrontFace( GL_CCW );

	/// BG Texture
	glBindTexture( GL_TEXTURE_2D, bg_texture_id );
        glBegin(GL_QUADS);
		glTexCoord2f( 0.0f, 0.0f );
		glVertex3f( -30.0f,  30.0f, -10.0f );
		glTexCoord2f( 1.0f, 0.0f );
		glVertex3f( 30.0f,  30.0f, -10.0f);
		glTexCoord2f( 1.0f, 1.0f );
		glVertex3f( 30.0f, -30.0f, -10.0f );
		glTexCoord2f( 0.0f, 1.0f );
		glVertex3f( -30.0f, -30.0f, -10.0f );
	glEnd();


	// Finally, display rendered frame on screen
    gp_app->Display();
}

I’m quite certain the issue is something fairly trivial, but I haven’t had any luck searching via Google and on these forums. If you need any additional code, please feel free to ask, but I feel most of the non-GL code should be fairly intuitive. Many thanks for your time and assistance!

Someone from another forum figured it out, so I figured I’d replicate his answer here in case anyone was curious or may need the answer in the future.

This has been documented as a Common Mistake at
http://www.opengl.org/wiki/Common_Mistakes#Creating_a_Texture