/****************************************************************************
  FAST LINEAR COLOR RENDERER
  Russell C.H. Cheng, University of Wales,  Cardiff 21 Jan 1992

  The renderer assumes true 24-bit color with a linear memory frame-buffer
  of 4-byte integers, lowest byte is r, then g, then b, with the top byte
  not used.

  The renderer precalculates and stores the merged 24-bit rgb x-offsets.
  This avoids a separate interpolation for each of the r, g and b variables
  for every pixel.

  Entry:
  For clarity the required input variables are passed to the renderer
  as arguments, Details of each variable are given in the listing.  In a
  general program it will be more compact to hold these variables in a
  structure and pass a pointer to this.

  Exit:
  The renderer outputs directly to the designated frame-buffer.
****************************************************************************/

#define HRES 768  /*  horizontal resolution, adjust this as necessary */
#define VRES 512  /*  vertical resolution, adjust this as necessary   */

void FastLinearRend( int xmin,int xmax,int ymin,int ymax,
		int* xleft,int* xright,
		float r0,float g0,float b0,
		float z0,
		int x0,int y0,
        float dr_by_dx, float dr_by_dy, float dg_by_dx, float dg_by_dy, float db_by_dx, float db_by_dy, float dz_by_dx, float dz_by_dy,
		int* screen_buffer_ptr, float* z_buffer_ptr)
#if 0
int xmin,     /*  The extent of the polygon being rendered:                 */
    xmax,     /*  xmin and xmax give the x-values of the leftmost and       */
    ymin,     /*  rightmost pixels of the polygon, and ymin and ymax the    */
    ymax;     /*  largest and smallest y-values encountered in the polygon  */

int * xleft,   /* Pointers to arrays holding the x-value of the leftmost    */
    * xright;  /* and rightmost pixel occupied by the polygon on each       */
               /* scanline. The values xleft[ymin],..., xleft[ymax], and    */
               /* xright[ymin],..., xright[ymax] should all be set on entry */
               /* The arrays themselves in the main program should be each  */
               /* of size VRES                                              */

float r0,g0,b0; /* Base rgb values of the polygon at the pixel position     */
                /* x0, y0; each in the range 0.0 - 255.0 */

float z0;       /* Base z-distance of the polygon at pixel position x0, y0  */

int x0,y0;      /* Position of base pixel, this need not be a pixel of the */
                /* polygon, but is typically a vertex or the origin (0,0)  */

float  dr_by_dx, dr_by_dy,   /*  r, g, b color and       */
       dg_by_dx, dg_by_dy,   /*  z-distance increments   */
       db_by_dx, db_by_dy,   /*  in the x and y          */
       dz_by_dx, dz_by_dy;   /*  directions              */
  
int *  screen_buffer_ptr;    /* Pointer to the frame buffer base address   */
                             /* The frame buffer is assumed to be linear   */
                             /* memory, comprising VRES horizontal lines   */
                             /* with HRES pixels per line                  */

float *  z_buffer_ptr;       /* Pointer to the z-buffer base address */
                             /* The buffer-size is HRES*VRES         */
#endif
{
      float r,g,b,z,         /* current r g b z values */
            r1,g1,b1,z1;     /* r g b z values at position x0, y */

      float dx,dy;           /* offsets of current pixel position */
                             /* from that of base pixel           */

      int x,y;               /* current pixel position            */

      int *  screen_buffer;  /* pointer to current frame-buffer position  */
      float *  z_buffer;     /* pointer to current z-buffer position      */

      int col;               /*  This holds the 24-bit rgb color of the */
                             /*  leftmost pixel of the current scanline */

      int rgboffset[HRES];   /*  This array holds the merged     */
                             /*  24-bit rgb x-direction offsets  */

      /* find r1, g1, b1, z1, the rgbz value at (x0,ymin) */
      dy = (float)(ymin - y0);
      r1 = r0 + dr_by_dy * dy;
      g1 = g0 + dg_by_dy * dy;
      b1 = b0 + db_by_dy * dy;
      z1 = z0 + dz_by_dy * dy;

      /* find the merged 24-bit rgb x-offset values along a scanline  */
      for (x = xmin; x <= xmax; x++) {
          dx = (float)(x - x0);
          r = dr_by_dx * dx;
          g = dg_by_dx * dx;
          b = db_by_dx * dx;
          rgboffset[x] = ((int)r) + (((int)g)<<8) + (((int)b)<<16);
      }
    
      /* now go through each scanline */
      for (y = ymin; y<= ymax; y++)  {
          /* for each scanline, find the 24-bit color value at (x0,y) */
          col = ((int)r1) + (((int)g1)<<8) + (((int)b1)<<16);

          /* and find the z value at (xleft[y],y) */
          dx  = (float)(xleft[y] - x0);
          z   = z1 + dz_by_dx * dx;

          /* then render the scanline */
          screen_buffer = screen_buffer_ptr + y*HRES;
          z_buffer = z_buffer_ptr + y*HRES;
          for (x = xleft[y]; x<=xright[y]; x++) {
              if ( z < z_buffer[x] ) {
                   screen_buffer[x] = col + rgboffset[x];
                   z_buffer[x] = z;
              }
              z += dz_by_dx;
          }

          /* and increment the r1 g1 b1 z1 value ready for the next y */
          r1 += dr_by_dy;
          g1 += dg_by_dy;
          b1 += db_by_dy;
          z1 += dz_by_dy;
      }

}
