OpenGL - gluPerspective / glFrustum - zNear & zFar issues

I am writing an application for space exploration. I decided that light years are units and accurately simulate the distances between stars. After messing around and a lot of hard work (mainly studying the ropes), I have a camera that works correctly from the point of view of a spaceship passing through space.

At first, I did not pay attention to the zNear gluPerspective () parameter until I worked on planetary objects. Since my scale is in light year units, I soon realized that due to zNear being 1.0f, I would not be able to see such objects. After the experiment, I came to these numbers:

#define POV 45 #define zNear 0.0000001f #define zFar 100000000.0f gluPerspective (POV, WinWidth/WinHeight, zNear ,zFar); 

This works exceptionally well because I was able to cruise my solar system (position 0,0,0) and move up close to planets that look superbly lit and textured. However, other systems (not in the 0, 0, 0 position) were much more difficult to travel because the objects suddenly moved away from the camera.

I noticed, however, that strange visual glitches began to occur when traveling through the universe. The objects behind me will โ€œturn aroundโ€ and appear in front, if I swing 180 degrees in the Y direction, they will also appear in their original place. Therefore, when there is a skew in space, most stars correctly parallax, but some appear and move in the opposite direction (which, at least, causes concern).

Changing zNear to 0.1f immediately fixes ALL of these glitches (but will also not allow objects in the solar system). So I'm stuck. I also tried working with glFrustum and it gives exactly the same results.

To view the world, I use the following:

 glTranslatef(pos_x, pos_y, pos_z); 

With the appropriate camera code for orientation as needed. Even disabling camera functionality does not change anything. I even tried gluLookAt () and again it gives the same results.

Are there gluPerspective () restrictions when using extreme zNear / zFar values? I tried to reduce the range, but to no avail. I even changed my world units from light years to kilometers, scaling everything and using the larger zNear value - nothing. HELP!

+4
source share
3 answers

The problem is that you want to resolve too much at the same time. You want to see things on the scale of the solar system, and also have a semi-galactic scale. It is simply not possible. Not with real-time renderer.

There is so much floating point precision. And with your zNear, which is incredibly close, you basically destroyed your depth buffer for anything more than 0.0001 from the camera.

What you need to do is draw things based on distance. Next to the objects (on the scale of the solar system), one perspective matrix is โ€‹โ€‹drawn using one depth range (for example, from 0 to 0.8). Then, more distant objects with a different perspective matrix and a different depth range (from 0.8 to 1) are deleted. This is really the only way to do this job.

In addition, you may need to calculate the matrices for objects on the CPU in mathematics with double precision, and then translate them back to one precision for using OpenGL.

+4
source

OpenGL should not draw anything further from the camera than zFar, or closer to the camera than zNear.

But for things in between, OpenGL calculates the depth value, which is stored in the depth buffer, which it uses to indicate whether one object is blocking another. Unfortunately, the depth buffer has limited accuracy (usually 16 or 24 bits), and accordingly log2 (zFar / zNear) lost the coarse precision bits. Thus, the zFar / zNear ratio of 10 ^ 15 (~ 50 bits lost) inevitably causes problems. One option is to slightly increase zNear (if possible). Otherwise, you will need to look into the depth buffers or the logarithmic depth buffers.

+3
source

Nicole Bolas has already told you one part of the story. Another thing is that you should start thinking about a structured way of storing coordinates: to maintain the position of each object relative to the object that dominates it gravitationally and use the appropriate units for this.

So you have the stars. Distances between stars are measured in bright years. Stars rotate on planets. Distances within the star system are measured in light minutes to light hours. Planets revolve around satellites. Distances in the planetary system are measured in daylight hours.

To display such scales, you need to make several passes. Objects with their scales form a tree. First you sort the branches to close, then cross the depth of the tree first. For each branch level, you use the appropriate projection parameters so that the near โ†’ far clip planes are scraped off with the objects that were visualized. After each level clears the depth buffer.

+1
source

All Articles