Sign in to follow this  
CGameProgrammer

I need to manipulate the depth buffer. Are stencil buffers the way to go?

Recommended Posts

(BACKGROUND) I'm modifying the Dapple code, which is a modification of NASA's WorldWind project, and terrain is rendered quite sloppily. You can have multiple layers of terrain active, meaning the earth might be rendered using a very low-resolution texture, and then the ground near you may be rendered on top of that with high-detail images. The actual polygons are completely different; it's not drawing the same triangles with different textures. Because of this, you get something like z-fighting except that the polygons aren't actually coplanar; it's more like cross-stitching of polygons. The original solution was to clear the z-buffer before each patch of ground is drawn, but that defeated the whole purpose of using the z-buffer as it caused z-buffer errors. I hacked a solution where it clears the z-buffer only when a new layer is about to be drawn, which makes the terrain render correctly. However, it's impossible to draw objects on the terrain as they'll either always be hidden or always be shown, since the z-buffer is being cleared. (PROBLEM) Basically, there are a few ways to fix it: * Render the terrain as above, then do a second render-pass but only to the z-buffer. Or: * When drawing a terrain layer, overwrite the previous z-buffer values unless they were created by that same layer. The first solution seems the simplest but I'm not sure how. The extra time spent rendering will not be significant. I also don't know how to do the second solution. Stencil buffers? I've never messed around with those. EDIT: After further thought, the best solution is to render each layer to a separate surface, then render one surface on top of the other, with depth-testing disabled but depth-writing enabled. That way each layer will still do depth-testing with itself, but not with the layer underneath, and the finished scene will have intact z-data for everything so objects can be drawn on top. Well I guess this post doesn't have much purpose unless I can't figure out how to do the above. [Edited by - CGameProgrammer on March 2, 2007 7:56:30 PM]

Share this post


Link to post
Share on other sites
stanlo    212
If you have two intersecting triangles, will the line at which they intersect look jagged due to depth fighting? If this is the case, try using a higher resolution depth buffer (D24S8 instead of D16whatever). If that doesn't work you can try reducting your far plane:near plane ratio, and you'll get a better distribution of depth values.

Share this post


Link to post
Share on other sites
If you have polys that don't match up, you're going to have rendering artifacts - that's pretty much unavoidable. You need to decide which set of artifacts are acceptable to you.

What I'd probably do is render the base geometry with z reads and writes, then render any subsequent "detail" terrain geometry with z reads on, but z writes disabled. Then render the objects, characters, and buildings or whatever with z reads and writes on. With this, you'll lose any of the "detail" terrain geometry that conflicts with the base geometry or subsequent stuff, but, well, if that's the data you've got...

Share this post


Link to post
Share on other sites
I can't do that because the detail layers won't do z-buffering with themselves, and I need them to. I think the solution I suggested is the one I need, but I don't know how to render a quad that already has its own z-buffer.

Share this post


Link to post
Share on other sites
Try using the depth bias, you can find stuff about it in DX Reference at Advanced Topics/Pixel Pipeline. Or simply try to draw the upper poligons a bit higher.

You should put a picture here, it would be more clear.

Share this post


Link to post
Share on other sites
My solution was to render each layer, with z-buffering enabled, to separate surfaces, then paste one layer on top of another without z-buffering, with undrawn pixels being transparent. How do I go about doing that?

To illustrate the problem, here is the bottom layer:


Here is the smaller detailed layer:


Here they are, drawn together:


That is not z-fighting; the polygons are totally different. Some of the detailed layer's polygons are lower than the other layer's, and some are higher. Vertices are totally different, not just height values, but X and Z as well.

If the z-buffer is cleared before each new layer is drawn, you get this:


...which is correct. However, because the z-buffer for each previous layer is thrown out, it is no longer possible to draw objects on the ground correctly. For example, this following screenshot:


The jagged red line on the bottom is drawn at ground level but you can see it through the mountains because z-buffer information for that layer was discarded.

Actually, what I could do is render the detail layer(s) with z-reading disabled, then render them again with it enabled. That should fix everything, albeit at the cost of speed. I'll try that.

[Edited by - CGameProgrammer on March 5, 2007 12:08:57 PM]

Share this post


Link to post
Share on other sites
I got it working! Whew. I render the detail layer twice, first with z-reading disabled to wipe out the previous z-buffer only where the detail is drawn, then I render the layer again with z-reading enabled. It has to be rendered again to make sure it does z-buffering with itself.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this