1

I am using 32bit float values which I input into the vertex shader for the x,y,z positions of every vertex. But, I have read that opengl uses 24bit for depth buffer and 8 bit for stencil buffer.

Since, I am copying the same 32bit float in gl_position that I receive as input in vertex shader, I want to understand how does opengl convert this 32bit float to 24bit for depth testing.

genpfault
  • 51,148
  • 11
  • 85
  • 139
user007
  • 2,156
  • 2
  • 20
  • 35

1 Answers1

2

The gl_Position in the vertex shader is a clip space coordinate. There will be a division by w to generate normalized device coordinates, where the visible range is [-1,1] in OpenGL (by default, can be changed nowadays). Those values will be transformed according to the currently set glDepthRange parameters to finally get the window space z value, which is in the range [0,1].

The depth buffer must just store these values, and - very similar to color values which often store only even 8 bit per channel values - an integer depth buffer is used to represent fixed point values in that range.

Quoting from setction 13.6 "coordinate transformations" of the OpenGL 4.5 core profile spec (emphasis mine):

z_w may be represented using either a fixed-point or floating-point representation. However, a floating-point representation must be used if the draw framebuffer has a floating-point depth buffer. If an m-bit fixed-point representation is used, we assume that it represents each value k/(2^m-1), where k in {0,1,...,2^m- 1}, as k (e.g. 1.0 is represented in binary as a string of all ones).

So, the window space z_w value (which is in [0,1]) is just multiplied by 2^m -1, and rounded to integer, and the result is stored in the buffer.

derhass
  • 43,833
  • 2
  • 57
  • 78
  • 1) So, I am bound to loose precision when using depth testing, since it will be rounded off to the nearest integer? If I have a huge number of objects in the scene, say 10^7, then I cannot ensure that depth testing will be accurate? 2) Since you have quoted from OpenGL 4.5 spec, was there nothing in the spec for earlier versions? 3) I am not exactly sure about m-bit fixed point representation, is the float representation into bits? – user007 Apr 02 '17 at 19:00
  • 1) The hyperbolic distortion of z in a perspective situation will be a much bigger deal for your depth test precsion. Not sure why you relate the depth test to the number of objects, it doesn;t care about objects at all. 2) I just quoted the latest spec. The older specs, back to 1.0, basically say the very same thing. 3) I don't even get that question. – derhass Apr 02 '17 at 19:09
  • The reason I worry about number of objects is, say, I want to assign a depth value to all the 10^7 objects, then given the floating point representation (IEEE 754) it could get difficult to assign different floats to objects based on their depth, due to the precision loss while representing floats. I don't know what hyperbolic distortion means, so I will try reading about it and see how it can affect depth testing. Just wanted to know if I can correctly differentiate between this large number of objects based on there unique depths. – user007 Apr 02 '17 at 20:08
  • Well, with a 24 bit depth buffer, there are 2^24 different depth values, which is 1.7*10^7, so yes, you can represent them. But you must be careful with all the transformations and floating-point representations in-between. – derhass Apr 02 '17 at 23:09
  • Yeah! But I doubt if it is achievable. I have just read that you cannot represent 0.2 in float using the (sign, exponent, mantissa) format. Now since there will be rounding off in float representation and then again when opengl will convert it to an integer. So figuring out the smallest depth value (which I am thinking of adding to zero to get each object's depth) is not really possible. – user007 Apr 03 '17 at 02:33
  • I don't think that your conclusion is true. From the fact that 0.2 can't be exactly represented does not follow any of what you say. With standard IEEE single precision floats, you have a 23 bit mantissa, this means you have 2^23 different values in the [0.5,1) interval alone. now with 24 bit fixed point depth buffer, you have 2^23 values in the range (0.5,1], which is a bit tricky due to the odd shift, but doable. And for values below 0.5, the float precision is just _higher_. Also note that you simply can use a 32bit float depth buffer in OpenGL, if you want to. – derhass Apr 03 '17 at 07:59