Adafruit_GFX library implementing color interpolation for li

Breakout boards, sensors, other Adafruit kits, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
quarterturn
 
Posts: 76
Joined: Mon Mar 23, 2015 11:05 pm

Adafruit_GFX library implementing color interpolation for li

Post by quarterturn »

I'm working on 3D code for pygamer which uses shaded triangles via linear interpolation of vertex colors. It basically helps low-poly objects look smoother by shading each triangle to blend with the colors of the surrounding triangles.

I understand GFXcanvas1::drawFastRawHLine sets the color of the whole line via memset. It then seems like the for loop sets a bitmask to... make it displayable?

I'm not sure I get what's going on so for now I plan on just writing to the buffer a pixel at a time like so:

Code: Select all

/**************************************************************************/
/*!
   @brief    interpolated color horizontal line drawing into the canvas buffer
   @param    x   Line horizontal start point
   @param    y   Line vertical start point
   @param    w   length of horizontal line to be drawn, including first point
   @param    color1  start color
   @param    color2  end color
*/
/**************************************************************************/
void GFXcanvas1::interpolateFastRawHLine(int16_t x, int16_t y, int16_t w,
                                  uint16_t color1, uint16_t color2) {
  uint8_t alpha = 0xff;
  int16_t stop = x + w;
  int16_t i = 0;
  while (i < w) {
    uint8_t weight = i*32/wl
    if (weight!=alpha) {
      alpha = weight;
      buffer[x + i + y * WIDTH]  = interpolate(color1, color2, alpha);
    }
    i++;
  }   
}
(Colors are interpolated as uint16_t 565 values broken down into uint8_t RGB and then put back to uint16_t 565.)

Is going pixel-by-pixel to the buffer going to be siginifcantly slower than writing to the raw buffer? I'm trying to keep this part simple so I can focus on all the other mistakes that's crop up elsewhere.

Thanks!

User avatar
quarterturn
 
Posts: 76
Joined: Mon Mar 23, 2015 11:05 pm

Re: Adafruit_GFX library implementing color interpolation fo

Post by quarterturn »

Here's the triangle shader btw:

Code: Select all

/**************************************************************************/
/*!
   @brief     Draw a triangle with face-shading
    @param    x0  Vertex #0 x coordinate
    @param    y0  Vertex #0 y coordinate
    @param    x1  Vertex #1 x coordinate
    @param    y1  Vertex #1 y coordinate
    @param    x2  Vertex #2 x coordinate
    @param    y2  Vertex #2 y coordinate
    @param    color0 16-bit 5-6-5 vertex 0
    @param    color1 16-bit 5-6-5 vertex 1
    @param    color2 16-bit 5-6-5 vertex 2
*/
/**************************************************************************/
void Adafruit_GFX::shadeTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
                                int16_t x2, int16_t y2, uint16_t color0, uint16_t color1, uint16_t color2) {

  int16_t a, b, y, last;

  // Sort coordinates by Y order (y2 >= y1 >= y0)
  if (y0 > y1) {
    _swap_int16_t(y0, y1);
    _swap_int16_t(x0, x1);
    _swap_int16_t(color0, color1);
  }
  if (y1 > y2) {
    _swap_int16_t(y2, y1);
    _swap_int16_t(x2, x1);
    _swap_int16_t(color2, color1);
  }
  if (y0 > y1) {
    _swap_int16_t(y0, y1);
    _swap_int16_t(x0, x1);
    _swap_int16_t(color0, color1);
  }

  startWrite();
  if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
    a = b = x0;
    if (x1 < a)
      a = x1;
    else if (x1 > b)
      b = x1;
    if (x2 < a)
      a = x2;
    else if (x2 > b)
      b = x2;
    interpolateFastHLine(a, y0, b - a + 1, color);
    endWrite();
    return;
  }

  int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0,
          dx12 = x2 - x1, dy12 = y2 - y1;
  int32_t sa = 0, sb = 0;

  // For upper part of triangle, find scanline crossings for segments
  // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
  // is included here (and second loop will be skipped, avoiding a /0
  // error there), otherwise scanline y1 is skipped here and handled
  // in the second loop...which also avoids a /0 error here if y0=y1
  // (flat-topped triangle).
  if (y1 == y2)
    last = y1; // Include y1 scanline
  else
    last = y1 - 1; // Skip it
    
  uint16_t midpoint = interpolate(color2,color0,(y1-y0)*32./(y2-y0));
  uint16_t colorX = midpoint;
  uint16_t colorY = color1;
  uint16_t colorZ = color0;
  sa += dx01;
  sb += dx02;
  for (y = y0; y <= last; y++) {
    a = x0 + sa / dy01;
    b = x0 + sb / dy02;
    sa += dx01;
    sb += dx02;
    /* longhand:
    a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
    b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
    */
    if (a > b) {
      _swap_int16_t(a, b);
      _swap_int16(colorA, colorB);
    }
    interpolateFastHLine(a, y, b-a, colorA, colorB);
  }
  uint16_t colorU = midpoint;
  uint16_t colorV = color1;
  uint16_t colorW = color2;
  // For lower part of triangle, find scanline crossings for segments
  // 0-2 and 1-2.  This loop is skipped if y1=y2.
  sa = (int32_t)dx12 * (y - y1);
  sb = (int32_t)dx02 * (y - y0);
  for (; y <= y2; y++) {
    a = x1 + sa / dy12;
    b = x0 + sb / dy02;
    sa += dx12;
    sb += dx02;
    float weight = ((y-y0)*32.)/len2;
    uint16_t colorA = interpolate(colorX,colorZ,weight);
    uint16_t colorB = interpolate(colorY,colorZ,weight);
    /* longhand:
    a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
    b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
    */
    if (a > b) {
      _swap_int16_t(a, b);
      _swap_int16(colorA, colorB);
    }
    interpolateFastHLine(a, y, b-a, colorA, colorB);
  }
  endWrite();
}

User avatar
quarterturn
 
Posts: 76
Joined: Mon Mar 23, 2015 11:05 pm

Re: Adafruit_GFX library implementing color interpolation fo

Post by quarterturn »

It makes more sense now I see my functions should be in the GFXcanvas16 class.

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Products from Adafruit”