Graphics Reference
In-Depth Information
Figure 15.9 shows how the new scene should render
before
you implement
shadows. If you do not see the ground plane under your own implementation, the
most likely error is that you failed to loop over all triangles in one of the ray-
casting routines.
Listing 15.21: Scene-creation code for a two-sided triangle and a ground plane.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void
makeOneTriangleScene(
Scene
& s) { s.triangleArray.resize(1);
s.triangleArray[0] =
Triangle
(
Vector3
(0,1,-2),
Vector3
(-1.9,-1,-2),
Vector3
(1.6,-0.5,-2),
Vector3
(0,0.6f,1).direction(),
Vector3
(-0.4f,-0.4f, 1.0f).direction(),
Vector3
(0.4f,-0.4f, 1.0f).direction(),
BSDF
(
Color3
::green()
*
0.8f,
Color3
::white()
*
0.2f, 100));
s.lightArray.resize(1);
s.lightArray[0].position =
Point3
(1, 3, 1);
s.lightArray[0].power =
Color3
::white()
*
10.0f;
}
void
makeTrianglePlusGroundScene(
Scene
&s){
makeOneTriangleScene(s);
// Invert the winding of the triangle
s.triangleArray.push_back
(
Triangle
(
Vector3
(-1.9,-1,-2),
Vector3
(0,1,-2),
Vector3
(1.6,-0.5,-2),
Vector3
(-0.4f,-0.4f, 1.0f).direction(),
Vector3
(0,0.6f,1).direction(),
Vector3
(0.4f,-0.4f, 1.0f).direction(),
BSDF
(
Color3
::green()
*
0.8f,
Color3
::white()
*
0.2f, 100)));
// Ground plane
const float
groundY = -1.0f;
const
Color3
groundColor =
Color3
::white()
*
0.8f;
s.triangleArray.push_back
(
Triangle
(
Vector3
(-10, groundY, -10),
Vector3
(-10, groundY, -0.01f),
Vector3
(10, groundY, -0.01f),
Vector3
::unitY(),
Vector3
::unitY(),
Vector3
::unitY(), groundColor));
s.triangleArray.push_back
(
Triangle
(
Vector3
(-10, groundY, -10),
Vector3
(10, groundY, -0.01f),
Vector3
(10, groundY, -10),
Vector3
::unitY(),
Vector3
::unitY(),
Vector3
::unitY(), groundColor));
}
Figure 15.10 shows the scene rendered with
visible
implemented correctly.
If the
rayBumpEpsilon
is too small, then
shadow acne
will appear on the
green triangle. This artifact is shown in Figure 15.11. An alternative to start-
ing the ray artificially far from
P
is to explicitly exclude the previous triangle
from the shadow ray intersection computation. We chose not to do that because,
while appropriate for unstructured triangles, it would be limiting to maintain that
custom ray intersection code as our scene became more complicated. For exam-
ple, we would like to later abstract the scene data structure from a simple array
of triangles. The abstract data structure might internally employ a hash table or
tree and have complex methods. Pushing the notion of excluding a surface into
such a data structure could complicate that data structure and compromise its
general-purpose use. Furthermore, although we are rendering only triangles now,
Figure 15.10: A four-triangle
scene, with ray-cast shadows
implemented via the
visible
function. The green triangle is
two-sided.