If one wishes to render normally, where the closest object to the camera is rendered, you set the OpenGL flags as follows:
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
So i would assume that doing:
glDepthFunc(GL_GREATER);
glEnable(GL_DEPTH_TEST);
Would also allow me to render the fragments furthest away from the camera instead. However I see no output when setting the flags like this. (no other modification has been done to my application)
How can you render the fragments furthest away from the camera?
The depth range is from 0 to 1.
When you clear the depth, the whole array is filled with 1's by default.
You can change that with glClearDepth(0)
And you can change the range with glDepthRange(near, far)
GL_LESS (default) states this:
"Passes if the incoming depth value is less than the stored depth value."
GL_GREATER states:
"Passes if the incoming depth value is greater than the stored depth value."
So you need some cleared depth (0's) for greater depth to pile on. (to see furthest fragments only)
Related
I'm using OpenGL (with Python bindings) to render depth maps of models saved as .obj files. The output is a numpy array with the depth to the object at each pixel.
The seemingly relevant parts of the code I'm using look like this:
glDepthFunc(GL_LESS) # The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST) # Enables Depth Testing
... load the vertices and triangles, set the camera viewing position ...
depth = np.array(glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT), dtype=np.float32)
I can use this to successfully render depth images of the object.
However, what I want to do is, instead of obtaining the depth of the face closest to the camera along each ray, I want to obtain the depth of the face furthest from the camera. I want faces to be rendered regardless of in which direction they are facing – i.e. I don't want to backface-cull.
I tried to achieve this by modifying the above code like so:
glDisable(GL_CULL_FACE) # Turn off backface culling
glDepthFunc(GL_GREATER) # The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST) # Enables Depth Testing
... load the vertices and triangles, set the camera viewing position ...
depth = np.array(glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT), dtype=np.float32)
However, when I do this I don't get any depth at all rendered. I suspect that this is because I am using GL_DEPTH_COMPONENT to read out the depth, however I am not sure what to change to fix this.
How can I get the depth of the faces furthest from the camera?
Switching the depth test to GL_GREATER in priciple will do the trick, you overlooked just a tiny detail: You need to initialize the depth buffer differently. By default, it will be intialized to 1.0 when clearing the depth buffer, so that GL_LESS comparisions might update it to values smaller than 1.0.
Now, you want it to work the other way around, so you must intialize it to 0.0. To do so, just add a glClearDepth(0.0f) before the glClear(... | GL_DEPTH_BUFFER_BIT).
Furthermore, you yourself mention that you don't want backface culling for that. But instead of disabling that you can also switch the face culling around using glCullFace. You probably want GL_FRONT here, as GL_BACK is the default. But disabling it will work too, of course.
Make sure you use glDepthMask(GL_TRUE); to enable depth writing to the buffer.
Quick background of where I'm at (to make sure we're on the same page, and sanity check if I'm missing/assuming something stupid):
Goal: I want to render my scene with shadows, using deferred lighting
and shadowmaps.
Struggle: finding clear and consistent documentation regarding how to use shadow2D and sampler2DShadow.
Here's what I'm currently doing:
In the fragment shader of my final rendering pass (the one that actually calculates final frag values), I have the MVP matrices from the pass from the light's point of view, the depth texture from said pass (aka the "shadow map"), and the position/normal/color textures from my geometry buffer.
From what I understand, I need to find what UV of the shadow map the position of the current fragment corresponds to. I do that by the following:
//Bring position value at fragment (in world space) to screen space from lights POV
vec4 UVinShadowMap = (lightProjMat * lightViewMat * vec4(texture(pos_tex, UV).xyz,1.0)).xy;
//Convert screen space to 'texture space' (from -1to1 to 0to1)
UVinShadowMap = (UVinShadowMap+1)/2;
Now that I have this UV, I can get the percieved 'depth' from the light's pov with
float depFromLightPOV = texture2D(shadowMap, UVinShadowMap).r;
and compare that against the distance between the position at the current fragment and the light:
float actualDistance = distance(texture2D(pos_tex, UV).xyz, lightPos);
The problem comes from that 'depth' is stored in values 0-1, and actual distance is in world coordinates. I've tried to do that conversion manually, but couldn't get it to work. And in searching online, it looks like the way I SHOULD be doing this is with a sampler2DShadow...
So here's my question(s):
What changes do I need to make to instead use shadow2D? What does shadow2D even do? Is it just more-or-less an auto-conversion-from-depth-to-world texture? Can I use the same depth texture? Or do I need to render the depth texture a different way? What do I pass in to shadow2D? The world-space position of the fragment I want to check? Or the same UV as before?
If all these questions can be answered in a simple documentation page, I'd love if someone could just post that. But I swear I've been searching for hours and can't find anything that simply says what the heck is going on with shadow2D!
Thanks!
First of all, what version of GLSL are you using?
Beginning with GLSL 1.30, there is no special texture lookup function (name anyway) for use with sampler2DShadow. GLSL 1.30+ uses a bunch of overloads of texture (...) that are selected based on the type of sampler passed and the dimensions of the coordinates.
Second, if you do use sampler2DShadow you need to do two things differently:
Texture comparison must be enabled or you will get undefined results
GL_TEXTURE_COMPARE_MODE = GL_COMPARE_REF_TO_TEXTURE
The coordinates you pass to texture (...) are 3D instead of 2D. The new 3rd coordinate is the depth value that you are going to compare.
Last, you should understand what texture (...) returns when using sampler2DShadow:
If this comparison passes, texture (...) will return 1.0, if it fails it will return 0.0. If you use a GL_LINEAR texture filter on your depth texture, then texture (...) will perform 4 depth comparisons using the 4 closest depth values in your depth texture and return a value somewhere in-between 1.0 and 0.0 to give an idea of the number of samples that passed/failed.
That is the proper way to do hardware anti-aliasing of shadow maps. If you tried to use a regular sampler2D with GL_LINEAR and implement the depth test yourself you would get a single averaged depth back and a boolean pass/fail result instead of the behavior described above for sampler2DShadow.
As for getting a depth value to test from a world-space position, you were on the right track (though you forgot perspective division).
There are three things you must do to generate a depth from a world-space position:
Multiply the world-space position by your (light's) projection and view matrices
Divide the resulting coordinate by its W component
Scale and bias the result (which will be in the range [-1,1]) into the range [0,1]
The final step assumes you are using the default depth range... if you have not called glDepthRange (...) then this will work.
The end result of step 3 serves as both a depth value (R) and texture coordinates (ST) for lookup into your depth map. This makes it possible to pass this value directly to texture (...). Recall that the first 2 components of the texture coordinates are the same as always, and that the 3rd is a depth value to test.
I'm not sure why this is happening, I'm only rendering a few simple primitive QUADS.
The red is meant to be in front of the yellow.
The yellow always goes in-front of the red, even when it's behind it.
Is this a bug or simply me seeing the cube wrongly?
Turn the depth buffer and depth test on, or OpenGL would draw what is latter on the top.
Your application needs to do at least the following to get depth buffering to work:
Ask for a depth buffer when you create your window.
Place a call to glEnable (GL_DEPTH_TEST) in your program's initialization routine, after a context is created and made current.
Ensure that your zNear and zFar clipping planes are set correctly and in a way that provides adequate depth buffer precision.
Pass GL_DEPTH_BUFFER_BIT as a parameter to glClear, typically bitwise OR'd with other values such as GL_COLOR_BUFFER_BIT.
See here http://www.opengl.org/resources/faq/technical/depthbuffer.htm
I had the same problem but it was unrelated to the depth buffer, although I did see some change for the better when I enabled that. It had to do with the blend functions used which combined pixel intensities at the last step of rendering. So I had to turn off glBlendFunc()
I'm making a simple voxel engine (think Minecraft) and am currently at the stage of getting rid of occluded faces to gain some precious fps. I'm not very experimented in OpenGL and do not quite understand how the glColorMask magic works.
This is what I have:
// new and shiny
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// this one goes without saying
glEnable(GL_DEPTH_TEST);
// I want to see my code working, so fill the mask
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// fill the z-buffer, or whatever
glDepthFunc(GL_LESS);
glColorMask(0,0,0,0);
glDepthMask(GL_TRUE);
// do a first draw pass
world_display();
// now only show lines, so I can see the occluded lines do not display
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// I guess the error is somewhere here
glDepthFunc(GL_LEQUAL);
glColorMask(1,1,1,1);
glDepthMask(GL_FALSE);
// do a second draw pass for the real rendering
world_display();
This somewhat works, but once I change the camera position the world starts to fade away, I see less and less lines until nothing at all.
It sounds like you are not clearing your depth buffer.
You need to have depth writing enabled (via glDepthMask(GL_TRUE);) while you attempt to clear the depth buffer with glClear. You probably still have it disabled from the previous frame, causing all your clears to be no-ops in subsequenct frames. Just move your glDepthMask call before the glClear.
glColorMask and glDepthMask determine, which parts of the frame buffer are actually written to.
The idea of early Z culling is, to first render only the depth buffer part first -- the actual savings come from sorting the geometry near to far, so that the GPU can quickly discard occluded fragments. However while drawing the Z buffer you don't want to draw the color component: This allows you to switch of shaders, texturing, i.e. in short everything that's computationally intense.
A word of warning: Early Z only works with opaque geometry. Actually the whole depth buffer algorithm only works for opaque stuff. As soon as you're doing blending, you'll have to sort far to near and don't use depth buffering (search for "order independent transparency" for algorithms to overcome the associated problems).
S if you've got anything that's blended, remove it from the 'early Z' stage.
In the first pass you set
glDepthMask(1); // enable depth buffer writes
glColorMask(0,0,0); // disable color buffer writes
glDepthFunc(GL_LESS); // use normal depth oder testing
glEnable(GL_DEPTH_TEST); // and we want to perform depth tests
After the Z pass is done you change the settings a bit
glDepthMask(0); // don't write to the depth buffer
glColorMask(1,1,1); // now set the color component
glDepthFunc(GL_EQUAL); // only draw if the depth of the incoming fragment
// matches the depth already in the depth buffer
GL_LEQUAL does the job, too, but also lets fragments even closer than that in the depth buffer pass. But since no update of the depth buffer happens, anything between the origin and the stored depth will overwrite it, each time something is drawn there.
A slight change of the theme is using an 'early Z' populated depth buffer as a geometry buffer in multiple deferred shading passes afterwards.
To save further geometry, take a look into Occlusion Queries. With occlusion queries you ask the GPU how many, if any fragments pass all tests. This being a voxel engine you're probably using an octree or Kd tree. Drawing the spatial dividing faces (with glDepthMask(0), glColorMask(0,0,0)) of the tree's branches before traversing the branch tells you, if any geometry in that branch is visible at all. That combined with a near to far sorted traversal and a (coarse) frustum clipping on the tree will give you HUGE performance benefits.
z-pre pass can work with translucent objects. if they are translucent, do not render them in the prepass, then zsort and render.
In OpenGL you can draw only back-facing polygons, only front facing polygons or both. If you render a manifold triangle mesh, then clear the frame-buffer but not the depth buffer, then again render only the back facing polygons. What do expect to see?
I think the following answer given to me is wrong:
You should see the back facing
triangles. The first render pass will
result in the depth buffer having the
depth values of the triangles that are
front facing. The second render pass
you are rendering the back facing
triangles, hence those that have the
greatest depth value. Every triangle
that is rasterized will have its depth
value compared to the current depth
value for that pixel. Since the depth
buffer is set to all the closest depth
values (small values) but is
discriminating on the farthest depth
values (large values) the back facing
triangles will be rendered."
But I think the answer is:
Since the depth buffer is not cleared, and still contains the depth values of the front facing triangles, it would throw out the back facing triangles, and display nothing.
Which answer is correct?
It depends! Assuming the mesh is of an object that is a 2-dimensional manifold (i.e. topologically equivalent to a plane over sufficiently small areas around any point on the surface) and the first pass renders front- and back-facing triangles or just front-facing ones, and the depth function is GL_LESS or GL_LEQUAL then the second paragraph is right, since the front-facing triangles are always in front of the back-facing triangles and hence will always cause the depth test to fail.
Of course, if you use GL_GREATER or GL_GEQUAL as your depth function, the reverse is true so the first paragraph is correct.
I think the second paragraph is false.
Imagine a Moebius band which is a closed manifold. You can see clearly some back facing triangles (in white, front facing are in black) that are closer to the eye. In the second pass they will pass the depth test and be rendered: