Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (764)
Games in Android Showcase (229)
games submitted by our members
Games in WIP (852)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Some depth buffer precision experiments  (Read 3863 times)
0 Members and 1 Guest are viewing this topic.
Offline theagentd
« Posted 2016-02-27 04:48:41 »

Hey, I made this little program for testing the depth precision of different depth buffer formats and techniques.

https://drive.google.com/file/d/0B0dJlB1tP0QZVVpnMlZFbVk4N3c/view?usp=sharing

It's a small program that checks the depth buffer precision by drawing 256 quads closely stacked together. The program then reads back the resulting color texture and can figure out the strength of the depth bleeding by how "deep" into this stack of quads the depth fighting is occurring.

Controls:
 - Mouse to rotate camera
 - Mouse wheel to zoom in and out (quad size is scaled with zoom, but not spacing, so zooming out requires better depth precision)
 - Keys 1-9 to switch modes.

The program specifically tests the 16-bit uint, 24-bit uint and 32-bit float depth buffer formats, in combination with two techniques: swapping the near and far planes and using a 0.0 to 1.0 mapping instead of the default OpenGL -1.0 to +1.0 mapping using ARB_clip_control.



Visually inspecting the tests gave some very interesting results. Here are the things I found out from this program:

 - A 16-bit uint depth buffer has so low precision that no matter what mapping you use you will be able to utilize all possible values.

 - The normal OpenGL mapping of -1.0 to +1.0 needs to be converted to 0.0 to 1.0, ruining precision. A 24-bit uint depth buffer has more precision than the calculated depth value so the entire range is not utilized, and the depth is not temporally stable.

 - Since the limiting factor of a 24-bit uint depth buffer is the precision of the depth value being written, using a 32-bit float depth buffer produces identical results.

 - The standard DirectX mapping of 0.0 to 1.0 actually has slightly LESS precision than OpenGL's mapping. This is marginal, but still curious.

 - Reversing the depth on standard OpenGL should not have a significant impact as swapping (-1.0 to +1.0) to (+1.0 to -1.0) shouldn't affect float precision, but due to the scaling and biasing to (0.0 to 1.0) (or (1.0 to 0.0)) later, reversing the depth actually does slightly improve precision here, although very marginally.

 - The by far best mapping, having 20x higher precision than the runner-up, was reverse depth (1.0 to 0.0) mapping with a 32-bit float depth buffer. As shown here: http://outerra.blogspot.se/2012/11/maximizing-depth-buffer-range-and.html, this gives several times better precision than a 24-bit uint depth buffer thanks to the logarithmic precision distribution of floats being matched to the precision requirements of the depth values.

 - Even using reverse depth (1.0 to 0.0) mapping with a 24-bit uint depth buffer doubles precision as the depth values now have more than enough precision to utilize the entire 24-bit value space of the depth buffer. In addition, the depth bleeding becomes much more regular instead of the flickering, noisy mess.



To get a 0.0 to 1.0 (or the optimal 1.0 to 0.0) mapping of depth buffers, you'll need either NV_depth_buffer_float (supported by Nvidia and AMD cards) or ARB_clip_control (supported by Nvidia and some newer Intel GPUs). You'll also need a projection matrix that has that outputs depth values in a 0.0 to 1.0. JOML now supports creating such perspective/ortho matrices. My conclusion is that reverse depth always has equal or better quality, so even if the 1.0 to 0.0 depth range isn't supported it at least doesn't harm precision (it slightly improves it) to still use reverse depth, so there's no point in not using it everywhere, switching to the 1.0 to 0.0 depth range whenever it's supported for that sweet extra depth precision.

Using reverse depth means:
 - Clearing the depth buffer to 0.0 instead of 1.0.
 - Inverting all depth funcs (GL_LESS ---> GL_GREATER)
 - Swapping the near and far planes in the depth buffer.
 - Fixing problems with frustum culling since the near and far planes are swapped now.
 - (If the 1.0 to 0.0 depth range is supported): Make sure all matrices are generated for that depth range

Also, Vulkan defaults to the much more sane DX style mapping of 0.0 to 1.0, meaning that everything that supports Vulkan also supports the reverse 32-bit float mapping for super precision.


Myomyomyo.
Pages: [1]
  ignore  |  Print  
 
 

 
EgonOlsen (591 views)
2018-06-10 19:43:48

EgonOlsen (695 views)
2018-06-10 19:43:44

EgonOlsen (478 views)
2018-06-10 19:43:20

DesertCoockie (831 views)
2018-05-13 18:23:11

nelsongames (1026 views)
2018-04-24 18:15:36

nelsongames (1083 views)
2018-04-24 18:14:32

ivj94 (1664 views)
2018-03-24 14:47:39

ivj94 (622 views)
2018-03-24 14:46:31

ivj94 (1501 views)
2018-03-24 14:43:53

Solater (569 views)
2018-03-17 05:04:08
Deployment and Packaging
by philfrei
2018-08-20 02:33:38

Deployment and Packaging
by philfrei
2018-08-20 02:29:55

Deployment and Packaging
by philfrei
2018-08-19 23:56:20

Deployment and Packaging
by philfrei
2018-08-19 23:54:46

Deployment and Packaging
by philfrei
2018-08-19 23:53:08

Deployment and Packaging
by philfrei
2018-08-19 23:50:04

Java Gaming Resources
by philfrei
2017-12-05 19:38:37

Java Gaming Resources
by philfrei
2017-12-05 19:37:39
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!