173 lines
6.4 KiB
Markdown
173 lines
6.4 KiB
Markdown
---
|
|
geometry: margin=2cm
|
|
output: pdf_document
|
|
---
|
|
|
|
# Raytracer part B
|
|
|
|
This project implements a raytracer with Blinn-Phong illumination and shadows
|
|
implemented. The primary formula that is used by this implementation is:
|
|
|
|
\begin{equation}
|
|
I_{\lambda} =
|
|
k_a O_{d\lambda} +
|
|
\sum_{i=1}^{n_\textrm{lights}} \left(
|
|
f_\textrm{att} \cdot
|
|
S_i \cdot
|
|
IL_{i\lambda} \left[
|
|
k_d O_{d\lambda} \max ( 0, \vec{N} \cdot \vec{L_i} ) +
|
|
k_s O_{s\lambda} \max ( 0, \vec{N} \cdot \vec{H_i} )^n
|
|
\right]
|
|
\right)
|
|
\end{equation}
|
|
|
|
Where:
|
|
|
|
- $I_{\lambda}$ is the final illumination of the pixel on an object
|
|
- $k_a$ is the material's ambient reflectivity
|
|
- $k_d$ is the material's diffuse reflectivity
|
|
- $k_s$ is the material's specular reflectivity
|
|
- $n_\textrm{lights}$ is the number of lights
|
|
- $f_\textrm{att}$ is the light attenuation factor (1.0 if attenuation is not on)
|
|
- $S_i$ is the shadow coefficient for light $i$
|
|
- $IL_{i\lambda}$ is the intensity of light $i$
|
|
- $O_{d\lambda}$ is the object's diffuse color
|
|
- $O_{s\lambda}$ is the object's specular color
|
|
- $\vec{N}$ is the normal vector to the object's surface
|
|
- $\vec{L_i}$ is the direction from the intersection point to the light $i$
|
|
- $\vec{H_i}$ is halfway between the direction to the light $i$ and the
|
|
direction to the viewer
|
|
- $n$ is the exponent for the specular component
|
|
|
|
In this report we will look through how these various factors influence the
|
|
rendering of the scene. All the images along with their source `.txt` files,
|
|
rendered `.ppm` files, and converted `.png` files can be found in the `examples`
|
|
directory of this handin.
|
|
|
|
## Varying $k_a$
|
|
|
|
$k_a$ is the strength of ambient light. It's used as a coefficient for the
|
|
object's diffuse color, which keeps a constant value independent of the
|
|
positions of the object, light, and the viewer. In the image below, I varied
|
|
$k_a$ between 0.2 and 1. Note how the overall color of the ball increases or
|
|
decreases in brightness when all other factors remain constant.
|
|
|
|
![Varying $k_a$](examples/ka-demo.png){width=360px}
|
|
\
|
|
|
|
## Varying $k_d$
|
|
|
|
$k_d$ is the strength of the diffuse component. It also affects an object's
|
|
diffuse color, but at a strength that's affected by how much of it faces the
|
|
light. Much like the dark side of the moon, the parts of the object that aren't
|
|
pointed at the light will not receive as much of the light's influence. In the
|
|
image below, I varied $k_d$ between 0.2 and 1. Note how the part pointed to the
|
|
light changes the strength of the brightness as all other factors remain
|
|
constant.
|
|
|
|
![Varying $k_d$](examples/kd-demo.png){width=360px}
|
|
\
|
|
|
|
## Varying $k_s$
|
|
|
|
$k_s$ is the specular strength. It uses the object's specular color, which is
|
|
like its reflective component. When there is a large specular $k_s$, there's a
|
|
shine that appears on the object with a greater intensity. In the image below, I
|
|
varied $k_s$ between 0.2 and 1. Note how the whiteness of the light is more
|
|
reflective in higher $k_s$ values as other factors remain constant.
|
|
|
|
![Varying $k_s$](examples/ks-demo.png){width=360px}
|
|
\
|
|
|
|
## Varying $n$
|
|
|
|
$n$ is the exponent saying how big the radius of the specular highlight should
|
|
be. In the equation, increasing the exponent usually leads to smaller shines. In
|
|
the image below, I varied $n$ between 2 and 100. Note how the size of the shine
|
|
is the same intensity, but more focused but covers a smaller area as $n$
|
|
increases.
|
|
|
|
![Varying $n$](examples/n-demo.png){width=360px}
|
|
\
|
|
|
|
## Multiple lights
|
|
|
|
Multiple lights are handled by multiplying each light against an intensity
|
|
level, and then added together. Unfortunately, this means that the intensity of
|
|
each light can't be too bright. We rely on the image to not use lights that are
|
|
too bright. Because this may result in color values above 1.0, the final value
|
|
is clamped against 1.0. Below is an example of a scene with two lights; one to
|
|
the left and one to the right:
|
|
|
|
![Multiple lights](examples/multiple-lights-demo.png){width=360px}
|
|
\
|
|
|
|
## Shadows
|
|
|
|
Shadows are implemented by pointing a second ray between the intersection point
|
|
of the original view ray and each light. If the light has something obstructing
|
|
it in the middle, the light's effect is not used.
|
|
|
|
The soft shadow effect is realized by jittering rays across an area. In my
|
|
implementation, a jitter radius of about 1.0 is used, and 75 rays are shot into
|
|
uniformly sampled points within that radius. This also has the side effect that
|
|
rays that are closer to the original ray are sampled more frequently. Each of
|
|
these rays produces either 0 or 1 depending on if it was obstructed by the
|
|
object. Taking the proportion of rays that hit as a coefficient for the shadow,
|
|
we can get some soft shadow effects like this:
|
|
|
|
![Soft shadows](examples/soft-shadow-demo.png){width=360px}
|
|
\
|
|
|
|
## Light attenuation
|
|
|
|
Light attenuation is when more of the light is applied for objects that are
|
|
closer to a particular light source. The function that's applied is an inverse
|
|
quadratic formula with respect to the distance the object is from the light:
|
|
|
|
\begin{equation}
|
|
f_\textrm{att}(d) = \frac{1}{c_1 + c_2 d + c_3 d^2}
|
|
\end{equation}
|
|
|
|
Where:
|
|
|
|
- $f_\textrm{att}$ is the attenuation factor
|
|
- $d$ is the distance the object is from the light
|
|
- $c_1$, $c_2$, and $c_3$ are user-supplied coefficients
|
|
|
|
As you can see below, the effect of the light drops off with the distance from
|
|
the light (light coming from the left):
|
|
|
|
![Light attenuation](examples/attenuation-demo.png){width=360px}
|
|
\
|
|
|
|
## Depth Cueing
|
|
|
|
Depth cueing is when the objects further from the viewer have a lower opacity to
|
|
"fade" into the background in some sense. A good example of this can be seen in
|
|
the image below; note how the objects are less and less bright the further they
|
|
are away from the eye.
|
|
|
|
![Depth cueing](examples/depth-cueing-demo.png){width=360px}
|
|
\
|
|
|
|
## Shortcomings of the model
|
|
|
|
The Phong formula is just a model of how light works, and doesn't actually
|
|
represent reality. There's not actually rays physically escaping our eyes and
|
|
hitting objects; it's actually the other way around, but computing it that way
|
|
would not be efficient since we would be factoring in a lot of rays that don't
|
|
ever get rendered.
|
|
|
|
Also, one needs to take care to use reasonable constants. For example, if using
|
|
a different specular light color than the diffuse color, then it may produce
|
|
some bizarre lighting effects that may not actually look right compare to
|
|
reality.
|
|
|
|
# Arbitrary Objects
|
|
|
|
Here is an example scene with some objects that demonstrates some of the
|
|
features of the raytracer.
|
|
|
|
![Objects in the scene](examples/objects.png){width=360px}
|
|
\
|