Graphics Reference
In-Depth Information
43
44
45
46
47
48
49
50
shade(scene, T, P, unitN, w_o, L_o);
depthBuffer.set(x, y, depth);
image.set(x, y, L_o);
}
}
}
}
To just test coverage, we don't need the magnitude of the barycentric weights.
We only need to know that they are all positive. That is, that the current sample
is on the positive side of every line bounding the triangle. To perform that test,
we could use the distance from a point to a line instead of the full bary2D result.
For this reason, this approach to rasterization is also referred to as testing the edge
aligns at each sample. Since we need the barycentric weights for interpolation
anyway, it makes sense to normalize the distances where they are computed. Our
first instinct is to delay that normalization at least until after we know that the
pixel is going to be shaded. However, even for performance, that is unnecessary—
if we're going to optimize the inner loop, a much more significant optimization is
available to us.
In general, barycentric weights vary linearly along any line through a triangle.
The barycentric weight expressions are therefore linear in the loop variables x
and y . You can see this by expanding bary2D in terms of the variables inside
lineDistance2D , both from Listing 15.25. This becomes
( n · (x, y) + d )
/| n |
bary2D(A, B, C, Vector2(x, y)) =
( n · C + d )
/| n |
= r
· x + s
· y + t ,
(15.9)
where the constants r , s , and t depend only on the triangle, and so are invariant
across the triangle. We are particularly interested in properties invariant over hor-
izontal and vertical lines, since those are our iteration directions.
For instance, y is invariant over the innermost loop along a scanline. Because
the expressions inside the inner loop are constant in y (and all properties of T )
and linear in x , we can compute them incrementally by accumulating derivatives
with respect to x . That means that we can reduce all the computation inside the
innermost loop and before the branch to three additions. Following the same argu-
ment for y , we can also reduce the computation that moves between rows to three
additions. The only unavoidable operations are that for each sample that enters
the branch for shading, we must perform three multiplications per scalar attribute;
and we must perform a single division to compute z =
1
/
w , which is amortized
over all attributes.
15.6.4.4 Precision for Incremental Interpolation
We need to think carefully about precision when incrementally accumulating
derivatives rather than explicitly performing linear interpolation by the barycentric
coordinates. To ensure that rasterization produces complementary pixel coverage
for adjacent triangles with shared vertices (“watertight rasterization”), we must
ensure that both triangles accumulate the same barycentric values at the shared
edge as they iterate across their different bounding boxes. This means that we need
an exact representation of the barycentric derivative. To accomplish this, we must
 
 
Search WWH ::




Custom Search