Flickering in the far field?

Started by
7 comments, last by nefthy 18 years, 10 months ago
Hello! I've spent a while searching around about this, with no avail. I've got a feeling it's probably a pretty common problem, but the solution eludes me :( I'm drawing very simple objects (a rectangular shape for example) deep into my view frustum, but not past the far clip plane. As I move it towards the camera (origin), it seems to flicker a bit before becoming solid. I've considered a number of things, but have pretty much ruled them all out. If it were a lack of z-buffer precision, I would think there would still be *something* drawn. I've tried the program on multiple machines, so I've ruled out drivers (I hope). I've tried changing my near clip plane a lot, which varies the fov (and speed that the object approaches), but so long as the field of view is reasonable (i.e. the object is actually far away), the flickering takes place. I suppose I should definite what I mean by flickering. From one frame to the next, the object isn't consistently drawn. Right now I have three thin rectangular boxes coming towards the camera at different heights (constant y-axis values, constant 0.0 for x-axis, variable z-axis value from close to far clip plane to close to near clip plane). Far away, sometimes you only see two of them drawn for a few frames. Any help would be much appreciated! As I said, I'm sure this is probably something pretty common... makes me feel like a moron really :) Tony
Advertisement
It sounds like Z-buffer problems to me. The times the mesh is not drawn might be where the back part of the mesh is behind the far plane but gets (wrongly) Z-sorted to be in front of the objects front part. Hence the back part is drawn in favor but cannot be seen because it is outside the viewing frustum. Just a hunch though.

Greetz,

Illco
what are your values for far and near plane? and what are the coordinates of objects far away? What is the resolution of your z-buffer? As Illco said it sounds like a z-buffer problem.

The objects themselves are about 40 units wide, 1 unit tall, and 2 units deep. Eventually, they're supposed to be used as the wings of a bird, so the size is pretty close to "unchangeable".

I'm setting up the projection using "projection = PerspectiveProjection(-33, 33, -33, 33, 33, 1800)" (in Python). From what I understand, this is essentially a wrapper around glFrustum that does a little bit of house cleaning to work with the library I'm using (VisionEgg). The top-bottom and left-right planes should be equally sized because we're using a 768x768 viewport, instead of the full screen.

The units of +/-33 are chosen because of the geometry of the actual projection we plan on doing. The zNear value is chosen arbitrarily right now. We're going to do some experiments with cameras later on (tomorrow maybe) to calculate what the FOV needs to be.

The object itself follows the equation z = -1200.0 + 600.0*t, where t is in seconds. Essentially, we want it to approach at a constant velocity of 6m/s, and plan on using cm units everywhere.

As far as z-buffer resolution goes, I'm not sure how to even check that. Just doing a bit of reading I did find the calculations for calculating z-buffer precision and minimum spacing. I'm going to go have a cup of coffee or something and then read through that more thoroughly. Strange I missed that section my first time around...

A little further investigation. Using the formulas on http://www.opengl.org/resources/faq/technical/depthbuffer.htm and assuming that I have a 16-bit z-buffer (seems reasonable), then I get:

>>> z_buf(65534)
-1798.5305083759033
>>> z_buf(65533)
-1797.0634141342264

Which I believe should be (just barely) enough resolution, since the object is 2 units deep. Even when I bring zFar closer though (1200), I still get the flickering as the object approaches, and it's definitely not just for the first 2 or 3 frames while the object's back end enters the view frustum.

Edit: Just as a test, I stretched the blocks out along the z-axis to be around 16 units long, and get the same results.

Edit2: This is what I get when I graph the formula specified on the opengl site there. Looks like resolution shouldn't be too much of a problem (as far as I understand the problem at least).

Edit3: I'm not sure if this helps any, but the effect is MUCH more pronounced when the objects are off-center elevation wise (i.e. y != 0). for things flying really close to the centre, there is barely any (none when it's straight at us) flicker at all.

[Edited by - fat-tony on May 25, 2005 3:40:31 PM]
Z-buffer precision is not linear across the field. That is, more bits are used close to the near plane than close to the far plane. The end result is that polygons which are easily sorted approaching the near plane may not have enough bits to differentiate them as they approach the far plane.

It seems that your Z-buffer precision is "just enough", which actually means that it's plenty when rendered close to the near-plane, but insufficient when rendered close to the far-plane.

The "proper" way around is to use variable LOD models, decreasing the polygon precision as the polygons recede from the near plane. You should be doing this anyway otherwise, as triangles recede from the near plane and render less & less pixels to the framebuffer, the actual work to transform them remains constant. Thus, less pixels but same work.
Something I did once In a high-res outer-space scene with large, detailed gemoetry and very far view distances was to divid the rendering process into several sectors. Since objects were sparsely positioned, i was able to sort them by distance from the viewer and add them to three lists corresponding to arbitrary distance values.

I did all rendering while maintaining the same top bottom left and right clipping planes. I first rendered my stars, then set up the near and far clipping planes of my frustum to some very large numbers. I then rendered all objects with parts between those values. Then I cleared the depth buffer and changed the frustum values to smaller numbers with the far plane at the old near plane. Render, repeat until you reach the eye with the near plane.

The real downside to this is three zbuffer clears per frame. But it was the first solution I could come up with to render objects near and at such a distance at high resolution. Maybe split into two sections so you only need two clears of your scene permits. So if you ever need to do this now you won't need to risk time to try it.

Another note,
I remember thinking that instead of rendering objects that lie in two sectors, i would overlap the clipping sector by an amount equal to the largest dimension in one of my objects. The issue with that was because it is clipped at a far plane and not at a certain distance from the eye, either the sectors needed to overlap more based on the view angle, or my sort method needed to be based off of the plane which would be quite simple. I dont think I bothered to try either of those since i was just messing around.
I had the same problem in my space sim where you have view ranges form 1 meter to billions of kilometers. My problem was z-fighting (i.e. the ratio far/near was too big).

However, I do not think that 1800/33 is too big even for 16 bit z-buffers. (This is also a very interesting z-buffer page including a calculator).

So from my feeling, methods like z-buffer splitting - although well suited for space rendering - are overkill in that case. However, I'm nevertheless puzzled what could cause the problem.

I'd try to further isolate the problem. My "4 Pfennig":
- Definitely switch to a 24 bit z-buffer (z-precision at the far-plane < 0.005).
Even older cards (e.g. GF2 MX) can do that.
I don't know how it's done in Phyton. In SDL, you can set GL attributes before opening the GL window.
- What happens if you increase z-near to 100? (Then, z-precision at the far-plane is <0.5)
- Have you enabled backface culling? (glEnable(GL_CULL_FACE);)
If the flickering is caused by back faces that get drawn accidently because of z-imprecision, this should cancel the problem.
You could also just divide everything by 10 and you should be fine. You would have a 3 to 180 FOV and there Z-fighting will be gone.

This topic is closed to new replies.

Advertisement