Graphics Reference
In-Depth Information
to estimate coverage and eliminate the jaggies, just like MSAA normally does.
Our technique is thus independent of the MSAA mode. It can also run without
MSAA, but the wires will then look as jagged as (but not worse than) the rest of
the scene.
6.2.2 Method
The wire is represented in the vertex buffer much like one might normally design
a wire, with the exception that we need to be able to vary the wire's radius at
runtime, so we do not store final vertex positions but instead store the center of
the wire. The final vertex position will then be computed by displacing the vertex
along the normal. For this we provide a wire radius, in world-space units. This
would typically be a constant for wires and would be best passed in the constant
buffer, but for some types of objects (such as antenna towers, light posts, and
grass straws), it could make sense to store a radius value per vertex instead.
The first step is to estimate how small a radius we are allowed without violat-
ing our minimum one pixel width requirement given the current vertex position in
the view frustum. This scales linearly with the w-value of the transformed vertex,
depending on the field of view (FOV) angle and render-target resolution. With a
projection matrix computed the usual way with a vertical FOV, a constant scale
factor can be computed as in equation (6.1):
PixelScale = tan( FOV/ 2)
height
.
(6.1)
This value can be computed once and passed as a constant. The radius of a
pixel-wide wire is then given by multiplying by the vertex's w-value. The w-value
can be found by doing a dot product between the vertex position and the last row
of the view-projection matrix (or column, depending on the matrix convention
used). Once we know the radius of a pixel-wide wire, we can simply clamp our
radius to this value to ensure our wire is always at least one pixel wide. The
shader code for this is in Listing 6.1.
While adjusting the radius guarantees that we get gap-free wires, the result is
inevitably also that the wires will appear wider and wider as they go farther into
the distance if we do not also take the original unexpanded wire's pixel coverage
into account. Compare Figure 6.1 and Figure 6.2 for an illustration of this effect.
What we need to do is to compensate by computing the coverage of the real
unexpanded wire and fading the contribution accordingly. This is what will give
the wire its natural and alias-free appearance. This can be accomplished by
outputting the coverage value to alpha and enabling alpha blending. As shown
on the last line in Listing 6.1, the coverage fade factor is simply the original real
radius of the wire divided by the expanded radius. In other words, if the radius
was expanded to twice the size to cover one pixel, then the wire is half a pixel wide
and the coverage consequently 0.5. As the wire gets farther into the distance, it
Search WWH ::




Custom Search