Thread: Creating a z-buffer

  1. #1
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743

    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?
    My Website

    "Circular logic is good because it is."

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    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. #3
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    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?

    [edit]

    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]
    Last edited by DavidP; 03-05-2008 at 06:50 PM.
    My Website

    "Circular logic is good because it is."

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The fact that it is pixel based and not vertex based.

  5. #5
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    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.
    My Website

    "Circular logic is good because it is."

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    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. #7
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    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.
    My Website

    "Circular logic is good because it is."

  8. #8
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    ...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. #9
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    well like I said the per-pixel clipping was just there until I got my real clipping algorithm implemented.
    My Website

    "Circular logic is good because it is."

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Profiler Valgrind
    By afflictedd2 in forum C++ Programming
    Replies: 4
    Last Post: 07-18-2008, 09:38 AM
  2. Creating buffer overrun
    By suckss in forum C Programming
    Replies: 2
    Last Post: 11-10-2006, 05:21 AM
  3. Replies: 16
    Last Post: 10-29-2006, 05:04 AM
  4. Print out a buffer
    By SwarfEye in forum C Programming
    Replies: 4
    Last Post: 09-08-2006, 09:32 AM
  5. writing a pack-style function, any advices?
    By isaac_s in forum C Programming
    Replies: 10
    Last Post: 07-08-2006, 08:09 PM