A small ray tracer implemented in C++. I've used the following article as a reference.
cmake -S . -B build
cmake --build build
./build/ray-tracer > output.ppmrm -rf build/ # remove generated directoryHere is an overview of how our viewport (a virtual plane in 3D space) and camera are set up.
The camera is positioned at the default coordinates, the origin (0, 0, 0). The viewport is placed at a distance of 1 unit in front of the camera along the negative z-axis. Therefore, the center of the viewport is located at (0, 0, -1).
Since we want the viewport origin to correspond to the top-left corner of the image, we first determine the location of pixel (0, 0) and then define a way to iterate across the viewport.
To achieve this, we define two vectors:
Vu, which spans the horizontal edge of the viewportVv, which spans the vertical edge of the viewport
Using these vectors, we compute the per-pixel delta vectors along both axes. These delta vectors represent the step size between neighboring pixels and allow us to calculate the center position of each pixel on the viewport plane.
using the sphere definition to define whether the ray intersects with the sphere or not.
I've calculated the normals(a direction pointing straight out of the surface at the hit point) of the sphere that goes from the center, outwards. Then I've colored the sphere with the corresponding to normals coordinates colors.
After setting up the normals, the following question occured Which side of the surface did we hit?. Hence, we need to manage the case when the ray hits from the inside, thus inverting the normal. In consequence, I mananged to flip the normals to always face the ray.
The ground here is just a very large sphere with a center at (0, -100.5, -1) and with the radius of 100.
Antialiasing works by shooting multiple rays at different position inside the same pixel and averaging the returned colors. This approximates how real cameras capture light over an area instead of from a single point, producing smoother edges and reducing jagged artifacts.
The diffuse rendering is implemented by repeatedly generating random bounce directions above the surface and averaging the resulting light contributions.
After using gamma correction for accurate color intensity, I got the following rendered image.
The reflection direction for the metal material is computed by taking the incoming vector, removing its component along the surface normal (via the dot product), and flipping it outward, resulting in a mirror-like bounce, the result is on the first image below. Then, I've added a fuzzy reflection, the resulting rendered image is the second below.











