missing geometry - Possible z buffer issue?

Started by
8 comments, last by sirlemonhead 16 years, 1 month ago
I'm porting Aliens Vs Predator from a DirectDraw renderer to D3D8/9. I've got it mostly working fine on D3D8 but I notice rendering errors on certain levels. Level geometry would get over written, and objects behind walls would be visible (its not a transparency issue) I'm thinking something screwy is up with the z-buffer. I changed the code to d3d9 so I could use Pix, and here's what my scene looks like when presented: finished frame if you look at the wall that the left light source is attatched to, and compare it to the wall to the right, you'll notice a diagonal chunk of the wall is missing. here's a render output from Pix: before the wall chunk vanishes And then the next render output from pix: after the wall chunk vanishes As you can see, part of the wall vanishes. All i've done between these two updates is set a new texture and draw primitve. All I really want to know is if this looks like an issue with the Z Buffer? I clear it correctly, once at the start of the frame. Its set to Less_Equal. I'm using pre-transformed verts, no viewport. No D3D debug errors. I just really need a starting point so I can go through the code myself and try figure out what is causing this. Does it look like a z buffer issue? This problem doesnt happen in the original game code, and 99% of levels render fine with mine, so i'm a bit stumped..
Advertisement
Could possibly be a face culling issue. Are all the triangles defined the same way (Clockwise/Counter-Clockwise)? Do you use back-face culling in the first picture?

Edit: Spelling.
my blog contains ramblings and what I am up to programming wise.
No, the game conveniently specifies them in whatever order it feels like :
So I've got culling permenantly set to none. I could probably re-arranged the order that triangles are drawn, but it'd break in game mirrors. Would it be worth testing, even though I've always got culling turned off?
After a closer look at the photos, it does look like a drawing order problem (zbuffer). Open the second and third photos in different tabs in the browser and you can see the wall on top overwriting the bottom wall.

Hmm..do pre-transformed verts bypass the zbuffer test? Can you try using the painter's algorithm and see if that helps (simple back to front draw order). Other than that, I'm stumped. Hopefully someone more knowledgeable will come along.
my blog contains ramblings and what I am up to programming wise.
I see exactly what you mean, looking more closely. It is that top wall doing it.

pre-transformed doesn't bypass the test, as far as I know anyway..If I turn off z writes or z buffering, everything gets pretty messed up.

I'll see what I can do about draw order. The code is a bit hard to work with. I'm really just drawing things in whatever order the engine gives the vertex data to the rendering functions.

Are viewports needed for anything like this? The original code had one, but it was pre dx8 code, so I don't know If I need to reimplement it. Viewports should only really matter for clipping stuff that falls outside of my view range right?
Ok, it seems that geometry is only being "drawn" to my z buffer if i'm standing right up next to it. If it's even farther than a short distance, nothing will be added to the zbuffer. All my geometry z values are within 0.0 and 1.0 so there's some value somewhere screwing this up..

do near and far clip planes come into play for pretransformed verts, if the final output is a z value within the correct range?
I'm not completely sure, but you can try to add/modify near/far clip planes. Might give you better zbuffer precision.
my blog contains ramblings and what I am up to programming wise.
Yeah, have a look at some of my z values

z-value: 0.986093
z-value: 0.986204
z-value: 0.986225
z-value: 0.986108
z-value: 0.986093
z-value: 0.986141
z-value: 0.986138
z-value: 0.986093
z-value: 0.986114
z-value: 0.986141
z-value: 0.986869
z-value: 0.986939
z-value: 0.986941
z-value: 0.986872
z-value: 0.986939
z-value: 0.987052
z-value: 0.987055
z-value: 0.986941
z-value: 0.986941
z-value: 0.986869
z-value: 0.986872
z-value: 0.986944
z-value: 0.986941
z-value: 0.987055
z-value: 0.987058
z-value: 0.986872
z-value: 0.987058
z-value: 0.986944

most of them are like this. I guess dx is discarding them as they're so close to 1.0

The original game has values this high too, so i don't know how that ever worked. using a 24bit z buffer but i guess the accuracy isnt high enough?

I have no idea where the znear and zfar are even set in this code.
With those sorts of Z-values I'd imagine its your projection matrix that is effectively flattening the scene and the rasterizer is actually seeing some or all of the geometry as coplanar.

How did you get those Z-values? Using PIX and going to the depth buffer? They look like they could be close enough (especially as depth is non-linear) to collide.

Quote:I have no idea where the znear and zfar are even set in this code.
It's wherever you create the projection matrix - typically it'll be a D3DXMatrixPerspectiveFovLH() call. A very wide range or setting zNear to be 0.0 is a simple way of generating these sorts of errors. Depending on the scale of your geometry try setting them to something like 1.0 and 100.0 and experiment accordingly....

hth
Jack

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

There's no D3DX stuff in this code unfortunatly. It was really old Dx stuff. software T&L and execute buffers.

void D3D_ZBufferedGouraudTexturedPolygon_Output(POLYHEADER *inputPolyPtr,RENDERVERTEX *renderVerticesPtr) is the function that gets passed all the main geometry. levels, objects, players gun. Everything but decals and particles more or less.

RENDERVERTEX defines my vertex data, and it uses ints for the x, y and z values.

So, an example of the kind of values I can see coming into this function for the vertexes Z value are:

5315
5239
6143
3972

etc.

Firstly in the function, a ZNear value is calculated.

// Get ZNearZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);

ZNear is always 64.000000 (VDB_ClipZ is 64 and GlobalScale is 1)

The code then does
float oneOverZ = 1.0/(float)vertices->Z;

oneOverZ has values typically like

0.000156
0.000163
0.000162
0.000149

then the code does this
float zvalue = (float)vertices->Z+HeadUpDisplayZOffset;

HeadUpDisplayZOffset is defined as '0'

zvalue has values such as

6710.000000 (if vertices->Z was 6710)
etc

then
zvalue = 1.0f - ZNear/zvalue;

which has values such as

0.990462
0.990462
0.991779

which are the values that end up being set as z value of my vertex data inside the vertex buffer I use to render

so I don't get to set a ZNear and ZFar as such.

It's really confusing code to work with :

This topic is closed to new replies.

Advertisement