i
i
i
i
i
i
i
i
276 7. Advanced Shading
rection vector l and irradiance contribution (measured in a plane perpen-
dicular to the light source) E
L
. Many different types of light sources can
be defined, leading to different ways to compute l and E
L
—see Section 7.4.
In the material phase, the BRDF parameters and surface normal (as well
as the tangent and bitangent, in the case of anisotropic materials) are
found via interpolation or texturing. These values are used to evaluate the
BRDF for l and the view vector v. The result of the BRDF evaluation is
multiplied by a cosine factor and by E
L
to produce the outgoing radiance
contributed by the light source. Both phases are repeated for each light
source and the results are summed to produce the total outgoing radiance
for the fragment.
In many real-time applications, numerous light sources of various types
can be applied to surfaces described by a variety of materials. The sheer
number of combinations can pose difficulties. Imagine a game that sup-
ports just three types of light source (point, directional and spot). Each
mesh can be affected by no more than six light sources at once, and can
have one of five material types. In this relatively simple case, there are 420
shader combinations.
21
The number of combinations grows rapidly with
every addition—just adding a fourth light type (e.g., a projected texture
light) increases the number of combinations to 1050.
22
In real applica-
tions, the number is even higher. Valve’s Half-Life 2 has 1920 pixel shader
combinations [848].
In addition, the fact that both the light and material phase need to
be repeated for each light source affecting the object can lead to great
inefficiencies. Imagine a mesh modeling a long hallway, which is lit by
twenty spaced light sources. No location is lit by more than two light
sources, but if dynamic branches are not employed, then all twenty light
sources need to be computed for every pixel.
The most straightforward solution to both problems is to loop over light
sources dynamically in the pixel shader. Unfortunately, dynamic branches
in the pixel shader perform poorly on many GPUs. Even if branches are
reasonably fast, they still introduce some amount of overhead, which may
be unpalatable for performance-sensitive applications.
If dynamic branches are not used, then a different shader needs to
be generated for each possible combination of lights and material type.
Obviously, authoring each combination manually is impractical. A common
solution to this problem is to write a single large shader that is compiled
21
There are four possibilities for each of the six light “slots”—point, directional, spot,
and none. This is known in combinatorics as a case of “combinations with repetitions
allowed.” In this case, there are 84 possible combinations of lights for each material, for
a total of 420 combinations.
22
As in the previous case, but one more light type increases the number of possible
light combinations per material to 210, for a total of 1050 combinations.
i
i
i
i
i
i
i
i
7.9. Combining Lights and Materials 277
Figure 7.47. Lighting a game character. On the left we see the light sources affecting
the character. Arrows symbolize directional light sources and stars symbolize point light
sources. The size indicates brightness. The character is within the area of effect of one
directional light source and four point light sources. On the right we see the approxi-
mation enforced by the game’s shaders, which only support up to three directional light
sources and do not support point light sources at all. In this case, the two brightest
lights (the orange directional light source and the bright blue point light source) map to
the first two of the three available slots. The light blue point light source is converted
to a directional source. All other lights (the medium red point light and dim green and
purple point lights) are approximated by a single directional light (the pink arrow).
multiple times, using language features or code preprocessors to create a
different specialized version of the shader each time. This type of shader
is called an ¨ubershader or supershader [845, 1271]. Ideally one compiled
shader is produced ahead of time for each possible combination, since “on
the fly” compilation may introduce noticeable delays. This is not always
possible—in the case of the game Far Cry, the number of combinations
was too large for an exhaustive compilation. The developers had to find
the combinations used during gameplay and compile just those [887].
One tactic commonly used by game developers is to define a fixed,
cheap lighting model and approximate the actual lighting environment of
each object to fit the model. This reduces the number of combinations
and caps the lighting computations required. For example, imagine that a
game’s shaders support only one, two, or three directional lights. All other
types of lights affecting an object are converted into directional lights by
computing l and E
L
at the object’s center. The two brightest lights (based
on the value of E
L
) are used to fill the first two available lighting slots, and
any remaining lights are combined via a heuristic into a single directional
light, which fills the third slot (see Figure 7.47). Such approximations may
introduce visual artifacts, since they do not precisely represent the scene
lighting. In addition, since the approximation depends on the position of
the lit object, large continuous objects such as the hallway mentioned above
are problematic. Even if the hallway is chopped up into smaller pieces, the
lighting approximation may introduce undesirable discontinuities between
i
i
i
i
i
i
i
i
278 7. Advanced Shading
pieces. In addition, if the lights or objects move, then sudden changes in
the approximation may cause popping artifacts.
7.9.1 Multipass Lighting
Multipass lighting is another solution to the problem of combining lights
and materials. Here the idea is to process every light in a separate ren-
dering pass, using the hardware’s additive blending capabilities to sum the
results in the frame buffer. The application determines the set of light
sources affecting each object. Typically, the light sources have distance
attenuation functions that reach 0 at some finite distance. This enables
the application to use bounding volume intersection to narrow the list of
lights affecting each object. This is an O(mn) process [503, 691], and per-
forming it efficiently in large scenes is not trivial—relevant techniques are
discussed in Chapter 14. After the set of lights is determined, each object
is rendered once for each light, with a shader that computes the outgoing
radiance contribution for a single light source. Adding a new light source
type requires writing one new shader for each material type. In cases where
the light source illuminates just part of the object, hardware features such
as scissoring, depth bounds, and stencil tests can be used to minimize the
number of pixels processed. In theory, the screen could be cleared to black
and then the lights rendered additively, but in practice an opaque pass is
usually rendered first to lay down an ambient or environment-mapped base
value (see Chapter 8 for more details on ambient lighting and environment
mapping). The overall number of shaders is lower than in an ¨ubershader-
type approach. In our example with four direct light source types, up to
six lights and five material types, a multipass lighting approach requires
25 shaders (one for each combination of material and light type, including
ambient light) instead of 1050.
There are some practical issues with this approach. Multiple blending
passes to the frame buffer use a lot of memory bandwidth, which is a
scarce resource and is becoming relatively scarcer with time. The trend
is that GPU computation resources increase at a much faster rate than
available memory bandwidth [981]. Also, the mesh needs to be processed
multiple times by the vertex shader, and any pixel shader computations
that produce results used by the lighting process (such as texture blending
or relief mapping) need to be repeated for each light source. On a GPU that
does not perform blending correctly on sRGB frame buffers, lights will be
summed in nonlinear space, causing artifacts (see Section 5.8). Nonetheless,
many applications (mostly games) have used this technique to good effect.
i
i
i
i
i
i
i
i
7.9. Combining Lights and Materials 279
7.9.2 Deferred Shading
The availability of multiple render targets makes deferred shading aviable
alternative to traditional GPU rendering methods. The basic idea behind
deferred shading is to perform all visibility testing before performing any
lighting computations. In traditional GPU rendering, the Z-buffer nor-
mally shades as it goes. This process can be inefficient, as a single pixel
often contains more than one fragment. Each fragment found to be visible
at the moment it is being rendered has its shade computed. If the fragment
is completely covered by some later fragment, all the time spent computing
its shade is wasted. A rough front-to-back sort of objects can help minimize
this problem, but deferred shading completely resolves it and also solves
the light/material combination issues.
Deferred shading can be done with a Z-buffer by performing a ren-
dering pass that stores away the attributes of the closest visible surface.
Values saved include the z-depth, normal, texture coordinates, and mate-
rial parameters. These values are saved to multiple render targets accessed
by the pixel shader program. This is the only rendering pass needed in
which the objects themselves are sent through the pipeline. The first pass
establishes all geometry and material information for the pixel, so the ob-
jects themselves are no longer needed. The stored buffers are commonly
called G-buffers [1097], short for “geometric buffers.” Such buffers are also
sometimes called deep buffers, though this term can also mean storing mul-
tiple surfaces (fragments) per pixel, so we avoid it here. Figure 7.48 shows
typical contents of some G-buffers.
After this point, separate pixel shader programs are used to apply light-
ing algorithms or decals, or for post-processing effects, such as motion blur
or depth of field. A pixel shader program is applied with a viewport-filling
quadrilateral (or smaller polygon or object) to drive each computation. By
rendering this quadrilateral, each pixel covered has the pixel shader applied
to it. Pixel shader programs for lighting read the object attributes from the
saved buffers and use these to compute the color of the surface. Multiple
shader programs can be applied in this fashion, with the results added to
the output color buffer as computed.
One advantage of deferred shading over all the previously discussed ap-
proaches has already been mentioned: Fragment shading is done only once
per pixel (per shading program) and so has a predictable upper bound on
rendering cost. Deferred shading also has many of the advantages of multi-
pass lighting and lacks several of its drawbacks. Geometric transformation
is done only once, in the initial pass, and any computations needed for light-
ing are done only once. For example, say that five lights affect a surface,
and each light is computed in a separate pass. If the surface has a normal
map applied to it, the computations to perturb and transform the normal
i
i
i
i
i
i
i
i
280 7. Advanced Shading
Figure 7.48. Geometric buffers for deferred shading, in some cases converted to colors
for visualization. Left column: depth map, normal buffer, roughness buffer, sunlight
occlusion [1288]. Right column: texture color (a.k.a. albedo texture), light intensity,
specular intensity, near-final image (without motion blur; see Section 10.14 for the final
image). (Images from “Killzone 2,” courtesy of Guerrilla BV.)
will be done for each pixel for each light. With deferred shading, such
computations are performed once per pixel and stored, then used by each
light in turn. This advantage is even greater when relief mapping is used.
Deferred shading also takes advantage of the fact that GPUs render faster
when objects have the same attributes, e.g., share the same surface shader.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset