# Creating a z-buffer

This is a discussion on Creating a z-buffer within the Game Programming forums, part of the General Programming Boards category; So I am working on implementing a z-buffer in my graphics code, and I am having some problems with interpolating ...

1. ## Creating a z-buffer

So I am working on implementing a z-buffer in my graphics code, and I am having some problems with interpolating along the z axis. I am not sure exactly what the problem is, but maybe one of you can spot it.

First of all, here is my line function which draws from an (x,y,z) point to another (x,y,z) point. The two endpoints of the line have already been passed through the model view and projection matrices, divided by w, and the viewport transformation. Therefore the (x,y) coordinates are the actual coordinates on the screen where they should be plotted.

I do interpolation along the z-axis in the same way that I do color interpolation, so I am not exactly sure why it isn't work. Color interpolation works perfectly. Just interpolation along the z-axis doesn't work. I have highlighted in red everything that pertains to interpolating along the z axis.

Code:
```//draws a line the fast way, using Bresenham's algorithm
void line ( float *surface, point a, point b, color sColor, color fColor )
{
int Ax = a.x;
int Bx = b.x;
int Ay = a.y;
int By = b.y;

float Az = a.z;
float Bz = b.z;

color curColor = sColor;

int dX = abs(Bx-Ax);	// store the change in X and Y of the line endpoints
int dY = abs(By-Ay);

float dZ = Bz-Az;
if ( dZ < 0.0f ) dZ = -dZ;
float curZ = Az;

int Xincr, Yincr;
if (Ax > Bx) { Xincr=-1; } else { Xincr=1; }	// which direction in X?
if (Ay > By) { Yincr=-1; } else { Yincr=1; }	// which direction in Y?

if (dX >= dY)	// if X is the independent variable
{
int dPr 	= dY<<1;           // amount to increment decision if right is chosen (always)
int dPru 	= dPr - (dX<<1);   // amount to increment decision if up is chosen
int P 		= dPr - dX;  // decision variable start value

for (int counter = 0; counter <= dX; counter++)
{
//putpixel(screen, Ax, Ay, Color); // plot the pixel
putpixel ( surface, Ax, Ay, curZ, curColor );

curColor.r += ( fColor.r - sColor.r ) / dX;
curColor.g += ( fColor.g - sColor.g ) / dX;
curColor.b += ( fColor.b - sColor.b ) / dX;
curColor.a += ( fColor.a - sColor.a ) / dX;
curZ += dZ / dX;

if (P > 0)               // is the pixel going right AND up?
{
Ax+=Xincr;	       // increment independent variable
Ay+=Yincr;         // increment dependent variable
P+=dPru;           // increment decision (for up)
}
else                     // is the pixel just going right?
{
Ax+=Xincr;         // increment independent variable
P+=dPr;            // increment decision (for right)
}
}
}
else              // if Y is the independent variable
{
int dPr 	= dX<<1;           // amount to increment decision if right is chosen (always)
int dPru 	= dPr - (dY<<1);   // amount to increment decision if up is chosen
int P 		= dPr - dY;  // decision variable start value

for (int counter = 0; counter <= dY; counter++)
{
//putpixel(screen, Ax, Ay, Color); // plot the pixel
putpixel ( surface, Ax, Ay, curZ, curColor );

curColor.r += ( fColor.r - sColor.r ) / dY;
curColor.g += ( fColor.g - sColor.g ) / dY;
curColor.b += ( fColor.b - sColor.b ) / dY;
curColor.a += ( fColor.a - sColor.a ) / dY;
curZ += dZ / dY;

if (P > 0)               // is the pixel going up AND right?
{
Ax+=Xincr;         // increment dependent variable
Ay+=Yincr;         // increment independent variable
P+=dPru;           // increment decision (for up)
}
else                     // is the pixel just going up?
{
Ay+=Yincr;         // increment independent variable
P+=dPr;            // increment decision (for right)
}
}
}
}```

Now, it's important that you know the details of how I implement the z buffer. It is declared as a float*, and it is initialized to be of the size 640 * 480, with each value being initialized to 1.0f.

Here is how I implement z buffering in my putpixel function:

Code:
```void putpixel( float *surface, int x, int y, float z, color myColor )
{
//Clip points that are outside of our viewport
if ( x < masterViewPort.x || x > (masterViewPort.x + masterViewPort.width) )
return;
if ( y < masterViewPort.y || y > (masterViewPort.y + masterViewPort.height) )
return;

//Z buffering
if ( z > zBuffer[(y * 640) + x] ) return;

//Plot the point if it passes all tests.
surface[((y*640) + x)*3 + 0] = myColor.r;
surface[((y*640) + x)*3 + 1] = myColor.g;
surface[((y*640) + x)*3 + 2] = myColor.b;
}```
Does anyone see anything wrong with that code?

2. Where are you storing the z value at? It should be stored at buffer[ypos * buffer_pitch + xpos] where xpos and ypos are the projected screen coordinates of the point.

And your clip space system is incorrect.

3. Hm....after playing around with things it seems that by deleting this line:

Code:
`if ( dZ < 0.0f ) dZ = -dZ;`
It then works. I guess I was under the assumption that by dZ needed to be a positive value, but then after working it out mathematically in my head I realized I was wrong.

What do you see that's wrong with the point clipping?

Oh and I edited the following portion of the putpixel function to also make the z buffering to work:

Code:
```    //Z buffering
if ( z >= (zBuffer[(y * 640) + x]) ) return;
else zBuffer[(y * 640) + x] = z;```
[/edit]

4. The fact that it is pixel based and not vertex based.

5. In this case it is supposed to be pixel based.

Don't worry I am implementing a more complete clipping algorithm. It should be done within the next day or so actually. That was on the list of things to do.

6. The Z buffer is pixel based but the actual clipping should be vertex based. Clipping at the pixel level in software will prove to be quite slow.

I'd be interested to see what you come up with.

7. Sorry, Bubba, I have been so busy that I forgot to reply to this.

I did implement clipping the right way, and it does work very well, so you don't have to worry about what I had implemented beforehand.

To answer your question, I used the Sutherland-Hodgman polygon clipping algorithm. I like the algorithm a lot, and it is simple to implement. If you want to see the code, I will be glad to show you.

8. ...Sutherland-Hodgman polygon...
Then this is not per-pixel clipping. I was suggesting you use that exact algorithm because it clips at the vertex level.

9. well like I said the per-pixel clipping was just there until I got my real clipping algorithm implemented.