|
Notes for Wednesday February 24 class -- shadows and reflections
Shadows
Cast shadows are an example of secondary rays.
Once you have determined which surface your primary ray has hit,
you can then send a ray from that surface to each light source.
If this secondary ray misses all other objects in the scene,
then the surface is being lit by that light source,
and you can mix in the diffuse and specular components of
Phong reflectance.
But if the secondary ray hits any other object,
then the surface is not being lit by that light source,
and you should not mix in the diffuse or specular components of
Phong reflectance.
This secondary ray is formed by starting the ray at a point
just outside the surface point S, such as S + εN,
where ε is some very small number,
and shooting the ray into the direction
of the light LDir[i] .
In the example code, I have implemented cast shadows for you.
|
Reflection
Reflections are created by first computing
the mirror reflection direction from the primary ray,
then shooting a secondary ray from
a point just outside the surface:
V' = S + ε N
into that direction.
Whatever object is first hit by this secondary reflection ray,
if any, is then rendered.
Given the direction vector -W from
the surface back to the view point,
the direction of the reflection ray is formed by our usual method of
computing a reflection:
W' = 2 (-W • N) N - (-W)
The first object, if any, that this reflection ray
hits is then rendered, and that rendered color
is mixed into the final color of the object at this pixel.
In the example code, I have described the step by step
algorithm for implementing reflection.
Your job will be to replace this description
by an actual code implementation.
|
|
|
Refraction
Refraction occurs when light goes through a transparent
object, such as glass or plastic or water or diamond.
The light bends each time it encounters the interface
between the air and the refracting material.
In ray tracing we trace light backward from the eye.
When a ray from the eye encounters a transparent
refracting object, the ray changes direction, due to
refraction, which follows Snell's Law:
n1 sin(θ1) =
n2 sin(θ2)
where n1 and
2
are the indices of refraction for the two materials
(eg: air and glass),
and
θ1 and
θ2
are the incoming and outgoing angles
of the light path.
Index of refraction measures how slow light becomes
when it is traveling through any particular material.
The index of refraction of air is essentially 1.0,
because the speed of light through air is
very near to the speed of light in a vacuum.
The index of refraction of water is about 1.33,
of various kinds of glass is about 1.50,
and of diamond
is about 2.42.
The general idea for rendering a sphere
made of refracting transparent material
is that you first see where your ray V+tW
hits the front of the sphere (the first, smaller root of the quadratic equation).
Then you use Snell's Law to figure out
the direction of a ray inside the sphere.
You form that ray, and find the point of intersection with the
back of the sphere (the second, larger root of the quadratic equation).
Finally you use Snell's Law again
to figure out the direction of the ray that emerges
out from the rear of the sphere.
You find out what object is hit by that emerging
ray, if any, shade it, and use that color as the color of your glass sphere.
In the example code, I have described the step by step
algorithm for implementing refraction.
Your job will be to replace this description
by an actual code implementation.
|
|
|
Update on Feb 28:
Some people have been having trouble implementing
refraction from the hint in the code, so here is a more
detailed hint.
The first time your ray intersects your sphere, you
can use the raySphere() function.
But for the second intersection, when the
already refracted ray exits the sphere and
refracts again on its way out, you will want to implement
a modified function raySphereExit() , which
takes the second root of the quadratic equation
rather than the first root,
by adding the sqrt(D) term rather than subtracting it.
To refract a ray W that enters a surface which has a surface normal N,
you want to carefully break down W into component Wv
that is aligned with N and Wu that is perpendicular to N.
You can get Wv just by projecting W onto N:
Wv = N * (W • N)
The perpendicular vector is then whatever is left after Wv is removed from W:
Wu = W - Wv
Because the ray will be refracting,
you are going to rescale both Wv and Wu.
The new Wu' is a scaled version of Wu, according to Snell's law:
Wu' = Wu*n1/n2
where
n1 is the index of refraction before the ray passes the surface
and n2 is the index of refraction after the ray passes the surface.
Because you have rescaled Wu, you now need to rescale Wv, so that
the emerging refracted ray will be of unit length.
You can do this as follows:
___________
Wv' = normalize(Wv) * √1 - (Wu' • Wu')
The emerging refracted ray is now just the sum of Wu' and Wv':
W' = Wu' + Wv'
If you've done it right, you should get a result that looks something
like the image to the right.
In this case, I have set refractive index n to 1.5,
which is a typical refractive index for glass.
|
|
|
Homework
Due next Wednesday before the start of class
Change the code so that spheres and surface
reflectance properties are defined in Javascript,
rather than at each pixel
(like I did in class with lights).
Implement mirror reflection,
following the notes in the code.
For extra credit, implement refraction,
following the notes in the code.
Note that this is much more difficult
than reflection.
I'm not expecting everyone to be able to do this;
consider it a stretch goal.
For your homework, you can start with this code base:
hw3.zip
| |
|