Triangles are rasterized by finding all of the integer-coordinate points inside the three edges of the triangle1. For each such point, we also wish to interpolate an arbitrary number of other values to that point. We can both find these points and interpolate to them very efficiently using either the DDA algorithm or its rational-number cousin the Bresenham algorithm. As both are similar and you’re likely more familiar with working in real numbers than in rational numbers, we’ll discuss DDA here.
The DDA algorithm takes an -dimensional line segment, specified by its two the -vector end points, and finds all points on that line segment that have an integer coordinate in one particular dimension.
DDA
Officially, DDA stands for digital differential analyzer
but
I’ve never heard that name used except in explanatory texts like this
one. It’s always called DDA
, the DDA algorithm,
or the
DDA line-drawing algorithm.
Setup:
Find the first potential point:
Find all points:
Working backwards,
Given a point on the line segment with integer , is the next point on the line segment with integer as long as both is aligned with the segment and . So once we have one and , we just loop through adding to until we leave the segment (8).
To get we start with a vector aligned with the line segment by simple subtraction (3) and then get by dividing the entire vector by whatever it’s coordinate is (4).
Any time we have division, we have to consider division by zero. In this case division by zero would happen if the line has no extent in the direction, meaning there are either or points on the line with integer ; in either case, we can simply return the empty set: no meaningful points (1).
To get the initial we need to figure out how far the starting end of the segment is from an integer coordinate (, 5) make a vector offset that will move us to that point ( with , 6) and add that offset to the starting end of the segment (7).
All of this assumed we were stepping in the positive direction, so we swap the order of the segment endpoints if needed to make sure that’s the case (2).
The scanline algorithm uses DDA to find the pixels in a triangle by first using DDA in (i.e., finding points with integer values) on the three edge line segments; then using DDA in between pairs of points found this way that share the same value.
Bresenham’s line algorithm achieves the same results as DDA, but using only integer values. Because it uses only integers, it is both faster (integer arithmetic requires less hardware than floating-point hardware) and more precise (no rounding error) than DDA. It works on integer, rational, and fixed-point endpoints and outputs. Because of its efficiency and precision, it is commonly used in graphics hardware.
Bresenham’s line algorithm can be derived by writing out DDA using rational numbers and tracking the integral and fractional parts of each number separately. The result is less intuitive and more complicated code than DDA, but simpler and smaller hardware because the individual components require many fewer transistors.
Jack Elton Bresenham derived this algorithm not as a form of DDA, but rather by considering the implicit equation for a line, and also showed how it could draw other polygonal curves such as circles. Those generalizations are suitable for hardware implementation, but are not commonly implemented in hardware.
A naive implementation of DDA or Bresenham performs linear interpolation of values across a line or triangle. That means in particular that if one end of a line is at and has a red value of and the other end is at and has then at the interpolated will be .
While linear interpolation may seem intuitive, it is incorrect when paired with projection. To see this, consider the following two images:
If we use linear interpolation in 2D screen space, everything looking 2D and flat. This can be fixed by interpolating in hyperbolic coordinates instead.
In 1992 Jim Blinn wrote a paper explaining how interpolation could be made perspective-correct using something called hyperbolic interpolation; all graphics hardware now uses his approach.
Hyperbolic interpolation assumes that three components of the vector of values at each vertex of a triangle are special. and are special because they correspond to pixel locations; and is special because in homogeneous coordinates they are used to create frustums and perspective projection. It is traditional to also treat as special because it gives better [depth buffer] precision for up-close objects where errors would be more visible.
Suppose we have a supplied vertex coordinate . We first perform perspective projection in and by dividing by ; we also divide everyithing else by while we’re at it, getting . Note that is replaced by not . We use these divided coordinates in DDA to get a pixel coordinate . The and are the correct pixel and and the is the depth we use in the depth buffer, but the rest of the coordinates had a spurious division by which we now undo to get .
Hyperbolic interpolation
Consider the two points and .
Division by gives and .
Interpolation to the midpoint gives .
Multiplication by the interpolated gives .
It is common to wish to provide color and other material properties
at a different resolution than geometry. The usual way to realize this
is by (a) interpolating texture coordinates
to each fragment and
(b) at each fragment looking up the color and so on at those coordinates
in an image or array called a texture
. We have a separate page on using Textures in WebGL and
one on various applications of textures;
this section covers only basic texture lookups.
decal, adjusting the color only for a part of the triangle, and the alpha is composited on top of the interpolated object color.