home-made depth fill problem/questions?

Howdy, I’m attempting to make a software rasterizer that mimimcs the openGL pipeline.

The overall goal is to render the depth buffer to an image, to use for occlusion culling. (so i don’t have to use glReadPixels) i’m running into some huge problems when i’m trying to do the zbuffer fill for the polygons in my ransterizer.

Basicly, my problem can be summed up as:
When you multiply a point by MVP matrix, your w component can be negative (behind you) So when you do perspective division, the point becomes infront of you. Along side of this, the z value (which was once also negative) now becomes positive, which competly messes up the interpolation calculation for the z depth.

Now, i’ve attempted to fix this in a variety of ways, and ran into another problem, that the depth buffer is exponential, rather than linear. So, during my interpolation calculations:

dz = (vert1.z - vert0.z) /dx

the difference between z’s is a fraction, which, when divided by a fraction, then becomes a larger number, causing my interpolation values for depth to go above 1.f (bad mojo.) I’ve been trying to find information about this problem everywhere, and for some reason, it’s never mentioned. Can someone provide me with information to help solve this problem?

thank you

~Main

Originally posted by duhroach:
Howdy, I’m attempting to make a software rasterizer that mimimcs the openGL pipeline.
~Main

There are some open source software rasterizers you could start with. I was just looking at SoftGL today, and it also claims to mimimc the OpenGL pipeline.

Avi

Hey.

Check out Foley et al. Their description about the topic is a bit lacking, but you should use the matrix given in eq, 6.48.

The matrix transform the canonical perspective view volume into the canonical parrallel view volume. And while it does so, it does a few things

  1. makes the value in the resulting Z coordinate proportional to 1/Z, such that you can be sure that it can be interpolated linearly
  2. flips the sign, so you can use the same comparison function as you normally would
  3. Maps the value to [0,1]

I believe glFrustum does the same thing, except it maps to [-1,1], and does a mapping of a general perspective view volume, not just the canonical one.

Ok, so my problem then is with my matrix multiplication?
Does Foley et. al have a paper on that matrix you’re talking about?

this is my current screen projection algo. As you can see, i use the standard MVP matrix, derrived from glGet() functions. Now, at the end, i’m actually translating into screen space [0,1] so that my calculations match correctly. I just realized that this is capping my values between [0,1] so i won’t get negative values at all… Should i not do this translation on z? and leave it in clip space?

GVector4 pointToScreen(GVector3 point,GMatrix4 &mvp)
{
GVector4 & pt = GVector4(point);
pt*=mvp;

float pt_inv=1/pt[3];
//if W is behind us, scale us by the correct value. Z however, must remain the same (we need to test it.)
if(pt.w<0.f)
{
pt[0] *= -pt_inv;
pt[1] *= -pt_inv;
pt[2] *= pt_inv;
}
else
{

   pt[0] *= pt_inv;
 pt[1] *= pt_inv;
 pt[2] *= pt_inv;

}

//Note, since we’re doing scaling to [0,1] here, should we be gettin neg values?
pt[0]=(pt[0]+1.f)*0.5f;
pt[1]=(pt[1]+1.f)*0.5f;
pt[2]=(pt[2]+1.f)*0.5f;
return pt;
}

thanks again for the input, very helpful!
~Main

Foley et al. - I was refererring to the book.
see http://www.amazon.com/exec/obidos/tg/det…lance&n=507846.

As for the matrix, have you tried just taking the one from, say 2.11. glFrustum( p 43, from http://www.opengl.org/developers/documentation/version1_5/glspec15.pdf),,) and transforming it?

I don’t think you should do anything special depending on the w value - you should just dividide x,y,z with it, and you get values in the [-1,1] range.

I haven’t had a chance to try the glFrustum matrix yet.

I was hoping there’d be a solution in the mvp matrix somewhere. And i’m not quite sure how to derive the frustum plane distances.

Ok, so lemmie make sure i’ve got the right info here:
multiplication by the MVP matrix will put values in [-1,1] (clip space) however will leave the z value exponential? Which is what’s giving me the heart of my problem (inability to interpolate z correctly).

I should leave the division by -w alone, because it will give the correct values i need, and translate the z component to negative. However, this causes problems becuase my x & y values are now mirrored over the z plane so i’m getting incorrect results?

I’ll try the frustum transformation, will have to read up on how to derive those plane distances. Thanks for the info thus far!

~Main

The trick is, that the matrix makes the Z linear, by interpolating 1/Z, it does some clever scales/additions, such that you don’t have to change your comparison operator.

The solution is simple.

Just multiply by the frustum matrix, divide by w(not -w!), and use the resulting z value for z buffering. And yes, the Z value you get is linear.

jonasmr, thanks for all the great help. You’ve given me alot of heads up on this. I’ll try the frustum, and let ya know how it works.

BTW, the frustum matrix can use the frustum plane distances derived by the modelview & projection matricies correct? IE if i use the D values for those planes (that i’ve already calulated in my frustum culling) in the matrix, it will give me proper results?
AND, this matrix completly replaces the MVP matrix? or should it become MVF?

Thanks again!
~Main

take a look at the mesa sourcecode:
http://www.mesa3d.org/

The matrix should replace the Projection matrix, not the MVP.

At least, thats how its done in opengl, projection is done after lighting, which is done in eye space.

so
veye = MV * v;
calc lighting
vclip = P * v;

P is the frustum matrix