No Z-Fighting

Started by
8 comments, last by Jiia 18 years, 11 months ago
I have a strange question. My terrain is being rendered by rendering several layers over top of each other, yet does not disable the z-buffer during this process. When I say over top of each other, I mean 2 triangles have vertices that are in the exact same position. There is no z-fighting at all. Is this because the vertices are basically welded together, in the same exact positions? You can see a picture of the terrain here Is it safe to rely on this working consistently through other hardware? As in both no z-fighting, and also having the layers drawn in the same order? I'm using a Radeon 8500, and have access to no other cards. If I don't need to disable the z-buffer, I've just skipped a horrible situation that I thought I would need to face. Thanks for any suggestions.
Advertisement
If you are using the *exact* same geometry (probably by sharing the geometry with different texture coords or similar), and you've got your depth test on less-or-equal then you'll be fine.

BTW, nice texturing - is that some form of splatting?
I'm not using the exact same buffers. But triangles which overlap are individually exact.

So this is still okay? [smile]

Yep, it's splatting. There are some detail images in here

Thanks for your help
If you're not seeing any errors now then you're probably fine. Try testing on a 16bit depth buffer if you can.

The only thing you really need to watch for is if the vertices aren't actually in the same place. This usually happens when you apply decals etc. and you end up with decal verts lying on the edges of your terrain verts. Then the rounding errors can end up giving different results on the CPU (when you calculate the decal locations) and the GPU (when it renders the decal).
Quote:Original post by Jiia
Is it safe to rely on this working consistently through other hardware? As in both no z-fighting, and also having the layers drawn in the same order? I'm using a Radeon 8500, and have access to no other cards.

OrangyTang is correct [smile]

Mathematically speaking the geometry should generate exactly the same depth values each time it's rendered, so you should be fine. A lot of graphical effects are achieved using multiple passes where the geometry is unchanged, just the texture (and/or associated p-shader) is changed.

Z-Fighting tends to happen when geometry is very close to each other, or if various aspects of the view/projection/viewport change between passes that might cause different values to be generated.

Note that you might be able to get better performance by disabling Z-Writing on subsequent passes - as your first terrain pass fills the depth buffer with the correct values and there's not much point in re-writing the same values over and over again [grin]

Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Thanks for clearing that up for me.

edit: Oops, you answered one of my questions while I was asking. Too slow, I guess.

I'm wondering if it would actually optimize any decent amount to disable z-writes. There is an untexured base layer under the textured layers. This base has all triangles that exist in the area. Basically it just averages it's vertex colors based on the 1x1 texture mips applied to each point. It's needed because you can actually see through the layers where they overlap. And I planned on needed it for z-buffer problems. Guess maybe I was wrong about that one. Still, if disabling z-writes helps, it's not as much of a waste.

The only problem I can think of is that I might need to disable and re-enable the z-writing state a whole bunch of times. If a game object (rock or tree) uses the same textures as the landscape, I would like for them to share textures (not SetTexture() twice). But that would mean my terrain needs to be in the same rendering loop as other objects, where textured subsets are sorted.

So there are three methods that come to me..
1) Throw the terrain layers into the main renderer and leave the z-buffer alone.
2) Same as 1, but disable+enable z-write for every layer as it's rendered.
3) Render all terrain in it's own loop. Render all base areas, disable z-write, render all textured layers, enable z-write.

Option three would not be capable of sharing SetTexture states (with things other than terrain), but it wouldn't need to change to it's vertex shader technique or need to upload terrain chunk section data (only 32 bytes) to the shader more than once either.

Sorry, I guess I'm just thinking out-loud. I appreciate any suggestions, though.
Ok, I've just viewed your terrain shot and I should really admire its exciting texture, what has been your method for generating such a great one? a raw file or shaders?
I just can say onething which may or may not help make it a bit better, you can use a pixel shader code to refine your work just after drawing it on the scene, of course the performance cost may not worth the value, but you can test it anyway, you can wipe off the enlarged portions with a handy minifier using a catmull algorithm, although as I said it takes too much out of your GPU and finally you dont get anything special...
Visit galaxyroad.com which soon will have english contents too
Thank you for the compliment. My graphics card is a bit behind in the technology tree, so I wouldn't have a great time playing with pixel shaders.

Maybe eventually.
Be aware that different vertex shaders can produce different outputs (due to some optimizations). Even if you transform your vertices using the same code.
If you're not seeing any problems it's safe to assume that things works ok.
I've been doing this and when I changed some other things that didn't affect the position I started to get z-fighting. I took me quite a while to find out what the problem was, I thought I screwed up my shader code, but when I turned optimizations off it was working again.
Hehe, want to see my terrain shader?
vTerrainOutput vsMethod_Terrain(vTerrainInput IVertex){	vTerrainOutput OVertex;	OVertex.Pos = mul( float4(IVertex.Pos.xyz + vTerrain.Coordinates, 1.0f), ViewProj );	OVertex.Tex.x = IVertex.Pos.x / vTerrain.TextureSize;	OVertex.Tex.y = IVertex.Pos.z / vTerrain.TextureSize;	OVertex.Diffuse = IVertex.Diffuse;	return OVertex;}

vTerrain is a global structure specific to each area. The coordinates for each vertex are local, though, so I add the area coordinates. I could actually remove that and store absolute coordinates. Not sure if having really huge texture coordinates would be a problem, though.

One plus is that I can have a "default" area and render it everywhere that I didn't edit in the world editor.

This topic is closed to new replies.

Advertisement