As beginner to OpenGL (and computer graphics in general) I'm quite curious regarding the following questions:
I know what is Z buffer, it is a depth buffer which stores value ranging from 0 to 1. But why does its precision matter?
What is hidden surface problem?
What is the problem in using a linear Z buffer?
Why do we care about Z buffer precision?
Z buffer precision
In GL the depth buffer was developed so the precision is visually not decreasing with distance ... meaning that if you render infinite plane that crosses both znear
and zfar
planes and use the stored depth as color you would see the plane rendered as parallel bars with the same visual width. Something like this:
This provides more or less the same visual detail along the whole scene. However when you start looking at the geometrical accuracy its non linear and from numerical stats you will see that most of the <0,1>
range is very close to znear
.
Once our computers was able to handle bigger and more detailed scenes this behavior started to be a problem as suddenly we wanted to see details in more distant places where the depth value increment is usually bigger than the whole rendered object itself ...
To remedy this we can use linear dept buffer (for scenes with large dynamic depth range or very big objects).
lets have 16 bit depth buffer that means 2^16 values without sign as we have sign than its just 2^15 = 32768
possible values.
Now for linear depth that means that depth accuracy (minimal increment/change/delta) is
dz = (zfar-znear)/2^(bits-1)
for example let znear=0.1
and zfar=1000
then:
dz = (1000-0.1)/32768 = 0.03
across whole scene. Now when we get back to non linear depth the dz
is much smaller near znear
but hugely bigger near zfar
and using it as detail criteria is useless. Instead of that its better to comply this:
zfar/znear < 2^(bits-1)
hidden surface removal
its a workaround to Painters algorithm where objects more distant to camera are overpaintade by objects closer. The painter's algorithm in graphics is called Z-sorting
and it requires to render stuff in order. Depth buffering is a workaround where you store the depth value of already rendered stuff and render only if you are closer to camera. This eliminates the need of rendering in order while still achieve the same result.
However if dept precision is too low the rendering can not reliably tell what is closet and what not see this:
On the left the precision is good on the right its bad. As you can see the same geometry renders differently with wrong depth precision.
linear depth problems
Linear depth buffer is not GL native so you need to workaround the GL implementation a bit. Luckily with GLSL its really easy and cheap now without precission loss nor performance hits. For more info see the link above. However having linear depth means we got the same geometrical accuracy along whole scene. So for the same details we need more bits for depth buffer in case of close to znear
objects. That is why linear depth buffer is more suited for scenes with high dynamic depth range where non linear depth buffers behave poorly. So scenes with big objects going from znear
to zfar
like terrains, big space ships, towns etc ...
Why to care about depth precision?
to avoid rendering artifacts like depth fitting / depth tearing, wrong geometry intersections, wrong advanced effects etc ...
You need to take in mind that depth buffer bitwidth is fairly limited. The usuall values are 16/24/32
but for ages only 16/24
where available on majority of HW. Only in recent years we can have 32 and on some cards even 64 but IIRC that is no longer native depth buffer and needs additional code to enable it...
There are also other methods than linear depth buffer to achieve High dynamic depth range of the scene see: