Raytracing

Most info can be found at CS3241 Chapter 9.

Whitted ray tracing:

\[I = I_\text{local} + k_{rg}I_\text{reflection} + k_{tg}I_\text{transmitted}\]

Lighting computation:

\[I_\text{local} = I_ak_a + k_\text{shadow}I_\text{source}[k_d(N \cdot L) + k_r(R \cdot V)^n + k_t(T \cdot V)^m]\]

Scene description in raytracing:

Psuedocode:

render() {
  for each pixel:
    ray = eye to pixel
    pixelColor = trace(ray)
}

trace(ray) {
  hit = (t = inf, hitPos = null, hitNormal = null, hitMaterial = null)
  for each object in scene:
    if intersect(object, ray) is nearer, set as hit
  color = shade(ray, hit.hitPos, hit.hitNormal, hit.hitMaterial);
}

shade(ray, point, normal, material) {
  for each light source:
    trace a shadow ray to light source
    if intersect(light source, shadow ray):
      color += lighting(point, normal)
  if specular:
    color += trace(reflect(ray))
  if translucent:
    color += trace(refract(ray, material.refractiveIndexRatio))
}

## Ray Tracing Acceleration Research mostly within

Adaptive recursion depth control

Not very effective. Modifies the allowed recursion depth based on pixel.

First hit speed up using z-buffer

Also not very effective. Uses item buffer to identify first-hit object at each pixel.

Bounding volumes

Replaces complex object ray-intersection computation with simple object ray-intersection cocmputation. Ray-intersection with each object’s bounding volume; when no intersection, discard this object altogether.

Examples of bounding volumes:

Bounding volume hierarchy

First compute intersection with root bounding box ($a$). Then compute for the next bounding box containing that object (e.g. $c$). Then compute for the next bounding box containing that object (e.g. $c_3$). Keep computing until discard or lighting computation.

Usually good hierarchies are constructed manually.

Spatial subdivision

Subdivision of 3D space into regions Each regions has a list of objects in it. When ray traced into region, query the object list and perform intersection tests on those objects. Since we are looking for the nearest intersection, the ray should be traced from a front-to-back order through the regions.

Uniform Grid

Octree

Conditional schemes:

Distribution Ray Tracing

Whitted Distribution
hard shadows area lights, soft shadows
blur specular highlight (phong computation), with sharp reflections blurred reflections and refractions both
aliasing anti-aliasing
no caustics (focusing of light on surface) NO caustics
no color bleeding of diffuse surfaces NO color bleeding

Distribution ray tracing also demonstrates depth of field and motion blur.

Perturbing reflection ray also allows us to have glossy reflection.

Per pixel: shoot out random multiple primary rays, whose fetched colors are averaged. Per intersection: reflection, refraction, shadow rays are randomly perturbed.

Psuedocode:

render() {
  for each pixel:
    for each sample:
      ray = randomOffset(eye lens) to randomOffset(pixel)
      pixelColor = trace(ray)
    pixelColor /= samples
}

trace(ray) {
  hit = (t = inf, hitPos = null, hitNormal = null, hitMaterial = null)
  for each object in scene:
    if intersect(object, ray) is nearer, set as hit
  color = shade(ray, hit.hitPos, hit.hitNormal, hit.hitMaterial);
}

shade(ray, point, normal, material) {
  for each light source:
    trace a randomPerturbed(shadow ray) to Area light source
    if intersect(light source, shadow ray):
      color += lighting(point, normal)
  if specular:
    color += trace(randomPerturbed(reflect(ray)))
  if translucent:
    color += trace(randomPerturbed(refract(ray, material.refractiveIndexRatio)))
}

Raytracing on GPU