PDA

View Full Version : Depth Buffer Issue: Rendering Background Last Whites Out Other Textures



RocketDarkness
09-04-2012, 12:02 AM
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
http://i.imgur.com/51Z1s.png

No Background
http://i.imgur.com/WfVMv.png

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!

RocketDarkness
09-06-2012, 12:30 AM
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.



I am pretty sure glTexParameter() calls are applied PER TEXTURE and not globally. That means that the current active texture (for the last call to glBindTexture) will have its state affect by these. Also, I believe that you need to provide minification/magnification filters for an OpenGL texture to be valid.

What ends up happening is, if you comment out the background call (including the glBindTexture), the active texture at the end of render() will be your teapot_texture_id. During the next render, the glTexParameteri calls get applied to teapot_texture_id and the texture becomes valid for usage. Then you switch to the plane texture (which is not properly set up, hence your ground plane being screwed up) and then back to the teapot texture and your teapot renders fine.

Try applying these texture sampler settings to EACH texture, during initialization. You generally do not want to be reapplying them on runtime, unless you have to change their state.

V-man
09-06-2012, 05:22 AM
This has been documented as a Common Mistake at
http://www.opengl.org/wiki/Common_Mistakes#Creating_a_Texture