Graphics Reference
In-Depth Information
correctly, and break the program at the test location when an assertion is
violated. Thus, they help to identify failure cases without requiring that
you manually step through the correct cases.
2. Immediately reduce to the minimal test case. This is often a single-triangle
scene with a single light and a single pixel. The trick here is to find the
combination of light, triangle, and pixel that produces incorrect results.
Assertions and the GUI click-to-debug scheme work well for that.
3. Visualize intermediate results. We have just rendered an image of the
barycentric coordinates of eye-ray intersections with a triangle for a
400,000-pixel image. Were we to print out these values or step through
them in the debugger, we would have little chance of recognizing an incor-
rect value in that mass of data. If we see, for example, a black pixel, or a
white pixel, or notice that the red and green channels are swapped, then we
may be able to deduce the nature of the error that caused this, or at least
know which inputs cause the routine to fail.
15.4.5 Shading
We are now ready to implement shade . This routine computes the incident radi-
ance at the intersection point P and how much radiance scatters back along the eye
ray to the viewer.
Let's consider only light transport paths directly from the source to the surface
to the camera. Under this restriction, there is no light arriving at the surface from
any directions except those to the lights. So we only need to consider a finite
number of
v i values. Let's also assume for the moment that there is always a line
of sight to the light. This means that there will (perhaps incorrectly) be no shadows
in the rendered image.
Listing 15.17 iterates over the light sources in the scene (note that we have
only one in our test scene). For each light, the loop body computes the distance
and direction to that light from the point being shaded. Assume that lights emit
uniformly in all directions and are at finite locations in the scene. Under these
assumptions, the incident radiance L_i at point P is proportional to the total power
of the source divided by the square of the distance between the source and P .
This is because at a given distance, the light's power is distributed equally over
a sphere of that radius. Because we are ignoring shadowing, let the visible
function always return true for now. In the future it will return false if there is
no line of sight from the source to P , in which case the light should contribute no
incident radiance.
The outgoing radiance to the camera, L_o , is the sum of the fraction of incident
radiance that scatters in that direction. We abstract the scattering function into a
BSDF. We implement this function as a class so that it can maintain state across
multiple invocations and support an inheritance hierarchy. Later in this topic, we
will also find that it is desirable to perform other operations beyond invoking this
function; for example, we might want to sample with respect to the probability
distribution it defines. Using a class representation will allow us to later introduce
additional methods for these operations.
The evaluateFiniteScatteringDensity method of that class evaluates
the scattering function for the given incoming and outgoing angles. We always
then take the product of this and the incoming radiance, modulated by the cosine
 
 
Search WWH ::




Custom Search