Right, I still expect z fighting, but what I would expect is:
- less z-fighting
- z-fighting at different distances, mainly bad z fighting at further distances
Following is a test program that should demonstrate what I am seeing. It simply sets up two FBOs, one with a 24bit depth buffer, and a second with a 32bit fp depth buffer. Then it draws two long rectangles that are nearly coplanar on each fbo. One drawn in white, the other drawn in black (black on top). The two fbo renderings are then blitted to the system fbo s.t. the 24bit fbo is on the left, and the 32bit fbo is on the right. What I expect is to see alternating black and white stripes at different depths for the two fbos. What I get is the exact same image for both. Near clip is at 0.0001 and far clip is at 1000.0 to force the issue.
Also attached is an image of the result. A second image is attached with the 32fp depth buffer switched to a 16bit depth buffer and near clip increased to 0.001. Using 16bit, I get the results I would expect.
BTW, change the format of one of the fbos to 16bit, and the expected occurs.
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdio.h>
int window ;
int width = 600;
int height = 600;
float eye[] = { 0.0, -1.0, 10.0 };
float lookat[] = { 0.0, 100.0, 0.0 };
float up[] = { 0.0, 0.0, 1.0 };
enum swizzle { X=0, Y=1, Z=2 };
float fov = 60.0;
struct FBO
{
GLuint id; // FBO Handle
GLuint colorID; // Color Attachment Handle
GLuint depthID; // Depth Attachment Handle
GLenum depth_format; // GL_DEPTH_COMPONENT24, ...
FBO() : id(0), colorID(0), depthID(0) {}
} ;
FBO fbo24 ;
FBO fbo32 ;
float near_clip = 0.001 ;
float far_clip = 1000.0 ;
void initFBO( FBO &fbo )
{
if( fbo.id != 0 )
{
glDeleteRenderbuffers( 1, &fbo.colorID );
glDeleteRenderbuffers( 1, &fbo.depthID );
glDeleteFramebuffers( 1, &fbo.id );
fbo.colorID = fbo.depthID = fbo.id = 0;
}
glGenFramebuffers( 1, &fbo.id );
glBindFramebuffer( GL_FRAMEBUFFER, fbo.id );
glGenRenderbuffers( 1, &fbo.colorID );
glBindRenderbuffer( GL_RENDERBUFFER, fbo.colorID );
glRenderbufferStorage( GL_RENDERBUFFER, GL_RGB, width, height );
glGenRenderbuffers( 1, &fbo.depthID );
glBindRenderbuffer( GL_RENDERBUFFER, fbo.depthID );
glRenderbufferStorage( GL_RENDERBUFFER, fbo.depth_format, width, height );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fbo.colorID );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, fbo.depthID );
}
void init()
{
#define GLEW_STATIC 1
glewInit() ;
fbo24.depth_format = GL_DEPTH_COMPONENT24 ;
fbo32.depth_format = GL_DEPTH_COMPONENT16 ;
initFBO( fbo24 );
initFBO( fbo32 );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glClearColor( 0.5, 0.5, 1.0, 0.0 ) ;
glEnable( GL_DEPTH_TEST );
}
void reshape( int w, int h )
{
if( w != width || h != height )
{
width = w ;
height = h;
glViewport( 0, 0, width, height ) ;
initFBO( fbo24 );
initFBO( fbo32 );
}
glMatrixMode( GL_PROJECTION ) ;
glLoadIdentity() ;
gluPerspective( fov, (float)w/h, near_clip, far_clip ) ;
glMatrixMode( GL_MODELVIEW ) ;
glLoadIdentity() ;
gluLookAt( eye[X], eye[Y], eye[Z],
lookat[X], lookat[Y], lookat[Z],
up[X], up[Y], up[Z] ) ;
}
void drawTest()
{
glColor3f( 1.0, 1.0, 1.0 );
glBegin( GL_QUADS );
glVertex3f( -20.0, 0.0, 0.0 );
glVertex3f( 20.0, 0.0, 0.0 );
glVertex3f( 20.0, 1000.0, 0.0 );
glVertex3f( -20.0, 1000.0, 0.0 );
glEnd();
glColor3f( 0.0, 0.0, 0.0 );
glBegin( GL_QUADS );
glVertex3f( -20.0, 0.0, 0.1 );
glVertex3f( 20.0, 0.0, 0.1 );
glVertex3f( 20.0, 1000.0, 0.1 );
glVertex3f( -20.0, 1000.0, 0.1 );
glEnd();
}
void draw()
{
glBindFramebuffer( GL_FRAMEBUFFER, 0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glBindFramebuffer( GL_FRAMEBUFFER, fbo24.id );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
drawTest();
glBindFramebuffer( GL_READ_FRAMEBUFFER, fbo24.id );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
glBlitFramebuffer( 0, 0, width, height,
0, 0, width/2, height,
GL_COLOR_BUFFER_BIT, GL_NEAREST );
glBindFramebuffer( GL_FRAMEBUFFER, fbo32.id ) ;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
drawTest();
glBindFramebuffer( GL_READ_FRAMEBUFFER, fbo32.id );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
glBlitFramebuffer( 0, 0, width, height,
width/2, 0, width, height,
GL_COLOR_BUFFER_BIT, GL_NEAREST );
glutSwapBuffers();
glutPostRedisplay() ;
}
void key( unsigned char key, int x, int y )
{
static float units = 1.0;
switch( key )
{
case 'q' :
glutDestroyWindow( window ) ;
exit( 0 ) ;
break ;
case 'n' :
near_clip += 0.001*units ;
reshape( width, height );
printf( "Near Clip = %f
", near_clip );
break ;
case 'N' :
near_clip -= 0.001*units ;
reshape( width, height );
printf( "Near Clip = %f
", near_clip );
break ;
case 'f' :
far_clip += 10.0*units ;
reshape( width, height );
printf( "Far Clip = %f
", far_clip );
break ;
case 'F' :
far_clip -= 10.0*units ;
reshape( width, height );
printf( "Far Clip = %f
", far_clip );
break ;
case 'u' :
units *= 10.0;
break;
case 'U' :
units /= 10.0;
break;
}
reshape( width, height ) ;
}
int main(int argc, char** argv)
{
glutInit( &argc, argv ) ;
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH ) ;
glutInitWindowSize( width, height ) ;
glutInitWindowPosition( 200, 200 ) ;
window = glutCreateWindow( "Depth Test" ) ;
init() ;
glutDisplayFunc( draw ) ;
glutReshapeFunc( reshape ) ;
glutKeyboardFunc( key ) ;
glutMainLoop() ;
return 0;
}