I'm writing a flight simulator and got stuck with the classic problem of this genre: the near plane of the viewing frustum must be close enough to make aircraft cockpit visible, the far plane has to be far away to enable visible distances with up to 40km.
The visibility distance or near/far ratio is indeed beyond the z-buffer precision ability of opengl and distant objects flicker violently. This is the place a fancy 3d engine leaves you alone with your problem and you need a true knowledge of opengl :). Probably i found the right way to fix the problem (OpenGL experts correct me if i'm wrong), but my solution misses the important bit. Altered renderer performs double pass rendering:
- in the first pass distant objects and background has to be displayed, near plane moved away, z-buffer is happy, terrain looks good but near objects are clipped away.
- in the second pass the projection matrix is adjusted for close range objects and should display the cockpit.
The unsolved problem: in the second pass all distant objects and background are invisible, hence i have the cockpit and black background behind it. The result of the second pass totally wastes the result of the first pass. Ergo planned overlay doesn't happen. Question: how to force the opengl to ignore the background color in the second pass so both pass results create desired overlay?
P.S. Here is the image of the status quo (near/far planes are at extremes to make all details visible, single pass without projection adjustments).
http://www.flickr.com/photos/43342833@N04/5995604542/sizes/l/in/photostream/
The buffer clearing happens only once per rendering cycle and and not involved between the 2 passes. Here the clearing code:
JoglContext jctx = (JoglContext) ctx;
GLContext context = context(ctx);
GL gl = context.getGL();
// Mask of which buffers to clear, this always includes color & depth
int clearMask = GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT;
gl.glPushAttrib(GL.GL_DEPTH_BUFFER_BIT);
gl.glDepthMask(true);
gl.glClearColor(r, g, b, jctx.getAlphaClearValue());
gl.glClear(clearMask);
gl.glPopAttrib();
The approach you describe is also used in the 2 passes: 1. "long distance" projection and terrain 2. "short distance" and the cockpit no clearing between, but after the second pass the background behind the cockpit is black. Maybe the glDepthRange function helps, got to check the manuals.
The zbuffer depth is 24 bits.