Crate tinyraytracer[][src]

This is a basic ray tracer. It is based on Understandable RayTracing in 256 lines of bare C++ Coming from a computer vision background, I had some idea how ray tracing might work, this is for me to actually understand it. To make it more fun, I wanna try and write documentation that’s going to cover some fundamental concepts as part of it.

( This is a work in progress and I don’t add documentation in a linear fashion, so it might be a bit early to try and read it) If there is anything you want to fix/comment on/request etc. Github Discussions is the best way to get in touch

What is Ray Tracing?

(caveat: I’m learning about it pretty much for the first time as I implement this.)

We have a 3-D model of some object in the world, and we want to express this model as a 2-D computer image. To construct our image we need to decide what color to assign to each pixel of the image. Since the real world is complex we don’t have an easy method to determine the color we should assign to each image pixel and we relay on simulations of light rays. Now, lets say more about what we mean by complex world and by simulation of a light ray.

The world is complex because objects have many colors, those colors change with lighting and reflection properties of the materials they are made of. Also, those properties interact with each other (light sources act in tandem on an object, light reflects from one object to another etc..). We do light ray simulation is by modeling how a ray of light behaves in the world. Direction at which it meets an object, how it is reflect from the object, how it eventually hits our eye etc…

To see how complex this can get, let’s take a look at our goal with this project vs. where we are now:

How we trace rays?

Since we are going to project from 3 to 2 dimension we need to pick a viewing angle (projection plane). This plane is going to We going to call this viewing angle a camera.

Ray-Sphere intersection

Question for future explorations

What if we have millions of objects in a scene?

I guess you can avoid checking most of the objects and limit your intersection checks based on light rays’ direction. How is it done in actual ray tracers?

How to make ray tracing differentiable?

Quick search got me this paper

Modules

blocks

In our world we have Spheres, Light Sources, Light Rays ang Materials.

vectors

We operate in a 3-D coordinate space. This is a helper struct for vector calculations.

Structs

CollisionState
LightBuilder
SphereBuilder

Constants

CANVAS_WIDTH_HEIGHT
DEFAULT_JITTER
MAX_RAY_BOUNCES

Functions

cast_ray

This is the light ray simulation. We go over the objects in the scene and check if our light ray intersect with them. If there is an intersection, we get the point of intersection and assign the color of the object the ray intersect with. Next we use the point of intersection and the lighting source in the scene to determine how lighting should affect the color at intersection point.

get_light_adjustments
jitter_along_normal

This function jitters a point along a noraml vector. Why do we need that? @ssloy explains: “Why is that? It’s just that our point lies on the surface of the object, and (except for the question of numerical errors) any ray from this point will intersect the object itself.”

light_is_shadowed

Shadow is like a negative light, we “cast a ray of shadow” for a certain hit point and light source. If the shadow ray hits the object, we know that the object is in shadow and we can’t see the light source. (Github Copilot wrote this line for me, how cool is that?)

main
reflective_ray_cast

Our ray of lights don’t stay in the same spot. If the hit some reflective material, they bounce off it like a ball. The is a recursive process. We start with a ray of light and cast it through the scene. Every time a ray hits some object and bounces off, well that’s a new ray. In real life ( I guess ) this process can go on until light losses energy, here we put a hard limit on the number of bounces.

render

This function builds an image by simulating light rays. Each pixel of an image is translated into a light ray. For each pixel, the light ray simulation returns the color the pixel should get.

Type Definitions

SceneObject