# Creating a z-buffer

• 03-05-2008
DavidP
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?
• 03-05-2008
VirtualAce
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.
• 03-05-2008
DavidP
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]
• 03-05-2008
VirtualAce
The fact that it is pixel based and not vertex based.
• 03-07-2008
DavidP
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.
• 03-07-2008
VirtualAce
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.
• 03-23-2008
DavidP
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.
• 03-23-2008
VirtualAce
Quote:

...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.
• 03-23-2008
DavidP
well like I said the per-pixel clipping was just there until I got my real clipping algorithm implemented. :)