Only moving a few inches can result in the colors going from dark to completely white. We can however, transform the non-linear depth values of the fragment back to its linear sibling. To achieve this we basically need to reverse the process of projection for the depth values alone. This means we have to first re-transform the depth values from the range [0,1] to normalized device coordinates in the range [-1,1].
Then we want to reverse the non-linear equation equation 2 as done in the projection matrix and apply this inversed equation to the resulting depth value. The result is then a linear depth value. We then take the resulting ndc value and apply the inverse transformation to retrieve its linear depth value:. This equation is derived from the projection matrix for non-linearizing the depth values, returning depth values between near and far.
This math-heavy article explains the projection matrix in enormous detail for the interested reader; it also shows where the equations come from. The complete fragment shader that transforms the non-linear depth in screen-space to a linear depth value is then as follows:.
Because the linearized depth values range from near to far most of its values will be above 1. By dividing the linear depth value by far in the main function we convert the linear depth value to the range [ 0 , 1 ]. This way we can gradually see the scene become brighter the closer the fragments are to the projection frustum's far plane, which works better for visualization purposes.
If we'd now run the application we get depth values that are linear over distance. Try moving around the scene to see the depth values change in a linear fashion. The colors are mostly black because the depth values range linearly from the near plane 0.
The result is that we're relatively close to the near plane and therefore get lower darker depth values. A common visual artifact may occur when two planes or triangles are so closely aligned to each other that the depth buffer does not have enough precision to figure out which one of the two shapes is in front of the other.
The result is that the two shapes continually seem to switch order which causes weird glitchy patterns. This is called z-fighting , because it looks like the shapes are fighting over who gets on top.
In the scene we've been using so far there are a few spots where z-fighting can be noticed. The containers were placed at the exact height of the floor which means the bottom plane of the container is coplanar with the floor plane. The depth values of both planes are then the same so the resulting depth test has no way of figuring out which is the right one. If you move the camera inside one of the containers the effects are clearly visible, the bottom part of the container is constantly switching between the container's plane and the floor's plane in a zigzag pattern:.
Z-fighting is a common problem with depth buffers and it's generally more noticeable when objects are further away because the depth buffer has less precision at larger z-values. If you want to affect a rectangle of values like in the sample above, simply draw a 2D quad in that area. What happens to those values can be controlled by you using the glStencilFunc , glStencilOp and glStencilMask functions.
The glStencilFunc call is used to specify the conditions under which a fragment passes the stencil test. Its parameters are discussed below. The mask value is set to all ones in case of an 8 bit stencil buffer , so it will not affect the test.
The glStencilOp call specifies what should happen to stencil values depending on the outcome of the stencil and depth tests. The parameters are:. Finally, glStencilMask can be used to control the bits that are written to the stencil buffer when an operation is run.
The default value is all ones, which means that the outcome of any operation is unaffected. If, like in the example, you want to set all stencil values in a rectangular area to 1, you would use the following calls:. In this case the rectangle shouldn't actually be drawn to the color buffer, since it is only used to determine which stencil values should be affected. The glColorMask function allows you to specify which data is written to the color buffer during a drawing operation.
In this case you would want to disable all color channels red, green, blue, alpha. Writing to the depth buffer needs to be disabled separately as well with glDepthMask , so that cube drawing operation won't be affected by leftover depth values of the rectangle.
This is cleaner than simply clearing the depth buffer again later. With the knowledge about setting values, using them for testing fragments in drawing operations becomes very simple. All you need to do now is re-enable color and depth writing if you had disabled those earlier and setting the test function to determine which fragments are drawn based on the values in the stencil buffer. If you use this call to set the test function, the stencil test will only pass for pixels with a stencil value equal to 1.
A fragment will only be drawn if it passes both the stencil and depth test, so setting the glStencilOp is not necessary. In the case of the example above only the stencil values in the rectangular area were set to 1, so only the cube fragments in that area will be drawn.
One small detail that is easy to overlook is that the cube draw call could still affect values in the stencil buffer. Find centralized, trusted content and collaborate around the technologies you use most. Connect and share knowledge within a single location that is structured and easy to search. On question 1: You can't directly read from the depth buffer in the fragment shader unless there are recent extensions I'm not familiar with.
Typical steps:. It has nothing to do with the value stored in the depth buffer. Unless you render in multiple passes, you cannot read and write to the depth buffer in a fragment shader.
That is to say, you cannot use a depth texture to read the depth and then turn around and write a new depth. If you only need the depth of the final drawn scene for something like shadow mapping, then you can do a depth-only pre-pass to fill the depth buffer. In the second pass, you would read the depth buffer but not write to it.
Stack Overflow for Teams — Collaborate and share knowledge with a private group. Create a free Team What is Teams? Collectives on Stack Overflow. Learn more. OpenGL - How to access depth buffer values?
Rendering depth to texture Ask Question. Every Fragment has a depth value. When rendering to a framebuffer that has no depth buffer, depth testing always behaves as though the test is disabled.
When depth testing is active, the depth value from the fragment is compared to the depth value from the matching sample currently in the framebuffer. Let us call the fragment's depth N, while the framebuffer's depth P. The depth test can take place before the Fragment Shader executes.
0コメント