ssloy / tinyrenderer

A brief computer graphics / rendering course
https://github.com/ssloy/tinyrenderer/wiki
Other
20.68k stars 1.98k forks source link

Why does the rendered line break when it is vertical —— lesson 1 #122

Closed Drincann closed 1 year ago

Drincann commented 1 year ago

In Second attempt - lesson 1, the expession used to calculate y changes as follows:

// first
int y = y0 + (y1-y0)*t; 
// second
int y = y0*(1.-t) + y1*t; 

Using the expression used in the second attempt, I found an exception when drawing a line with no slope (vertical). This line jitters back and forth within two pixels in the x direction like:

image

impl:

void CanvasContext::line(const Point& start, const Point& end) {
  int x0 = start.x, x1 = end.x, y0 = start.y, y1 = end.y;
  bool steep = false;
  if (std::abs(x1 - x0) < std::abs(y1 - y0)) {
    steep = true;
    std::swap(x0, y0);
    std::swap(x1, y1);
  }
  if (x1 < x0) {
    std::swap(x0, x1);
    std::swap(y0, y1);
  }

  for (int x = x0; x <= x1; ++x) {
    float t = (x - x0) / (float)(x1 - x0);
    int y = y0 * (1. - t) + y1 * t;  // what is wrong here and how it works?
    // int y = y0 + t * (y1 - y0); // this works fine

    if (steep) {
      this->point(Point(y, x));
    } else {
      this->point(Point(x, y));
    }
  }
}

calling:

// just create tgaimage instance like: this->image = new TGAImage(width, height, TGAImage::RGB);
Canvas* canvas = new Canvas(50, 50);
// store the drawing context
CanvasContext* _2dContext = canvas->createContext();
_2dContext->setColor(Canvas::COLOR_WHITE);

// call the method just given
_2dContext->line({5, 5}, {5, 20});
ssloy commented 1 year ago

In fact, in the expression y0(1.-t) + y1t there are two casts from floating point to int, the addition is integer. Therefore, there are more rounding errors than in the first one y0 + (y1-y0)*t

There is a pedagogical interest though to write y0(1.-t) + y1t because 1-t and t are barycentric coordinates of the current point w.r.t the segment (x0,y0) - (x1,y1), and this prepares ground for the barycentric coordinates in a triangle

Drincann commented 1 year ago

Thank you, great repository!