I have a 3D iPhone game done with OpenGL ES.
It’s a big world but with some tiny, first-person-view bits I need to paint up close, so I can’t reduce the depth range (zNear vs zFar) that glFrustumf() takes any further.
When surfaces meet for a Z-fight, I paint them slightly apart to stop them flickering. I’m also making the camera’s distance determine how far apart I adjust them, in cases where this is useful and needed.
It’s mostly OK, but there are some things whose perspective suffers by the separation, and making the separation smaller causes flicker. I’d love to paint surfaces closer together.
Is there any way to increase the depth buffer precision, so surfaces can be closer together without a narrower depth range?
If not, is there any other way around this?
I’m still using OpenGL ES 1.1 in the app, but am willing to upgrade if it’s worth it.
Thanks for your help.
Here’s how I create the depth buffer…
In init method:
// Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
glGenFramebuffersOES(1, &defaultFramebuffer);
glGenRenderbuffersOES(1, &colorRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
//Added depth buffer
glGenRenderbuffersOES(1, &depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
In resizeFromLayer method:
// Allocate color buffer backing based on the current layer size
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer];
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
//Added depth buffer
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
Here’s how I create the frustum…
const GLfloat zNear = 2.2;
const GLfloat zFar = 30000;
const GLfloat fieldOfView = 60.0;
GLfloat size = zNear * tanf(degreesToRadian(fieldOfView) / 2.0);
if (LANDSCAPE) { //for landscape clip & aspect ratio.
//parameters are: left, right, bottom, top, near, far
glFrustumf(-size/(backingWidth/backingHeight),
size/(backingWidth/backingHeight),
-size, size,
zNear, zFar);
}
Apparently 32-bit depth buffers aren’t supported in OpenGL ES 1.x.
Also, it seems that 16-bit depth buffers aren’t supported on iOS, so using
GL_DEPTH_COMPONENT16_OESwas just behaving as 24-bit, which is why I didn’t see any improvement when I usedGL_DEPTH_COMPONENT24_OESinstead!I confirmed this by checking
GL_DEPTH_BITSafter trying to set the depth buffer to 16 bit:Outputs:
Depth buffer bits: 24Oh well, at least now I know. Hope this helps someone else.