csci5607/assignment-1b/writeup.md
2023-02-20 22:23:40 -06:00

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}
\