During this block, I had 6 weeks to create a ray tracing engine. After these 6 weeks, there was a feature freeze. No more features could be added. The last 2 week were used to make a game using the ray tracing engine.
The core of the project was about math and optimizations. Since I was not allowed to utilize the GPU, I had to make sure my code was as optimized as possible. This meant I had to use multithreading, SIMD, and other high/low level optimizations to make sure my code was as fast as possible.
This time I got a basic voxel ray tracing engine without any features. My goal was to make a very robust
engine where every feature was controllable by the user. Using ImGui I was able to make a very
user-friendly
interface where I could easily change the settings of the engine.
Things I added to the engine:
Below You can view some of the features I added to the engine.
One of the first things I added to the engine was lights. I wanted to make sure I had a good
understanding
of how lights work in a ray tracing engine. I added all sort of lights like point light, area light, and
spotlight.
The way light works in a ray tracing engine is quite simple. You shoot a ray from the camera into the
scene.
When this ray hits a voxel, you send another ray towards the light source. If this ray hits a voxel on
its
way to the light source, that means the light is blocked and the pixel is in shadow.
But with a area light it's different. Since an area light is a 2D plane, you can't just shoot a ray
towards
the position of the light. You need to take a random position on the plane and shoot a ray towards the
voxel position.
This way you can calculate the soft shadows that an area light gives. And if you save the results from
multiple frames,
you can even get a better result. This is called stochastic sampling.
One of the biggest bottlenecks in a ray tracing engine is the ray traversal. This is the process of
shooting a ray anywhere in the scene and detecting if it hits anything.
Rendering just 1 frame needs a lot of rays. For each pixel you send a ray from the camera into the
scene. Then on the location where the ray hits a voxel, you need to send even more rays. These rays
are for lighting, ambient occlusion, etc.
Having a fast ray traversal is key to having a fast ray tracing engine. I used a technique called
brickmap to speed up the ray traversal. This technique is quite simple. You divide the world into
smaller chunks called bricks. Each brick has a bounding box that contains all the voxels in that brick.
When a ray hits a brick, you check if the brick has something in it. If it does, you go "inside" the
brick
and check all the voxels in that brick. If the brick is empty, you can skip all the voxels in that
brick. Allowing
you to skip a lot of voxels.
Everyone knows Conway's Game of Life. It's a simple cellular automata that has some simple rules.
I wanted to make a 3D version of this. I used the same rules as the 2D version, but now in 3D.
The rules are quite simple:
After the 6 week of developing the ray tracing engine, I had 2 weeks to make a game using the engine.
During which I made 2 small games.
The first game was a simple puzzle game where you could move a light source around the scene. The goal
is to light up all the cubes in the scene and to figure out where to place the light source so that all
the cubes meet their requirements.
Because some cubes need to be lit up and others need to be in the shadow.
The second game was more of a showcase and a play demo of the engine that an actual game. You can move
around the globe and shoot meteorites, while the sun (that lights up the scene) and a Millennium Falcon
rotate around the globe.
(ILO stands for Intended Learning outcome and the learning log is a document where I showcase all my work during this block)