This project implements a CPU-based ray tracer written in modern C++23.
It simulates the physics of light rays interacting with virtual 3D objects — spheres, planes, and reflective materials — to produce realistic rendered images (PNG).
Camera → Ray → Scene → Object → Material → Light → Image (PNG)
Each pixel in the image corresponds to a ray shot from the camera into the scene.
That ray may hit an object — if so, the intersection point, surface normal, and material determine the reflected color.
The rendering process repeats recursively for each reflection or bounce.
A ray is represented as:
R(t) = O + tD
- O → Origin (camera position)
- D → Normalized direction
- t → Distance along the ray
The intersection between a ray and a sphere of center C and radius r is computed by solving:
|O + tD - C|² = r²
Expanded:
t²(D·D) + 2t(D·(O−C)) + (O−C)·(O−C) − r² = 0
This is a quadratic equation in t.
The smallest positive root gives the nearest intersection point.
At the hit point P, the normal vector is:
N = normalize(P - C)
Light intensity = max(dot(N, L), 0)
Final color = albedo × intensity
Reflected direction:
R = D - 2 * dot(D, N) * N
+------------------+
| Camera Setup |
+------------------+
|
v
+------------------+
| Generate Rays |
+------------------+
|
v
+------------------+
| Intersect Scene |
+------------------+
|
v
+------------------+
| Compute Lighting |
+------------------+
|
v
+------------------+
| Reflect / Bounce |
+------------------+
|
v
+------------------+
| Accumulate Color |
+------------------+
|
v
+------------------+
| Save Image |
+------------------+
├── include/
│ ├── core/ # Rays, hit records
│ ├── geometry/ # Spheres, planes, hittables
│ ├── materials/ # Shaders and BRDFs
│ ├── math/ # Vector operations
│ └── rendering/ # Scene, camera, raytracer
├── src/ # Implementations
├── CMakeLists.txt
└── output.png # Final render
- VSCode Extension Devcontainer
- Docker
mkdir build && cd build
cmake ..
make -j$(nproc)./RaytracerThe rendered image (output.png) will be saved in the project root.
A simple reflective sphere over a plane lit by an ambient light.
Scene
├── Sphere(0,0,-1) radius=0.5 material=Metal
├── Plane(y=-0.5) material=Lambertian
└── Light(1,1,1) intensity=0.8
Result:
A metallic sphere reflecting the sky and the ground.
| Concept | Formula | Description |
|---|---|---|
| Ray | R(t) = O + tD | Parametric representation |
| Intersection | |O + tD − C|² = r² | Find t for hit point |
| Reflection | R = D − 2(N·D)N | Perfect mirror |
| Diffuse | I = max(0, N·L) | Lambert’s cosine law |
| Color | c = albedo × light | Final pixel contribution |
+-----------------+ +----------------+
| Raytracer |------>| Scene |
+-----------------+ +----------------+
| |
v v
+-------------+ +---------------+
| Camera | | Hittable |
+-------------+ +---------------+
|
v
+-------------+
| Sphere |
+-------------+
The entire rendering setup (camera, lights, objects, materials, etc.)
is defined in a simple JSON file.
{
"render": {
"width": 1920,
"height": 1080,
"samples_per_pixel": 200,
"max_depth": 10
},
"camera": {
"look_from": [
0.0,
0.5,
2.0
],
"look_at": [
0.0,
0.0,
-3.0
],
"vup": [
0.0,
1.0,
0.0
],
"fov": 45.0,
"aspect_ratio": 1.78
},
"lights": [
{
"position": [
5.0,
5.0,
5.0
],
"color": [
1.0,
1.0,
1.0
],
"intensity": 100.0
}
],
"objects": [
{
"type": "sphere",
"center": [
-1.5,
0.0,
-3.0
],
"radius": 0.5,
"material": {
"type": "lambertian",
"color": [
0.8,
0.3,
0.3
]
}
},
{
"type": "sphere",
"center": [
0.0,
0.0,
-3.0
],
"radius": 0.5,
"material": {
"type": "metal",
"color": [
0.9,
0.9,
0.9
],
"fuzz": 0.2
}
},
{
"type": "sphere",
"center": [
1.5,
0.0,
-3.0
],
"radius": 0.5,
"material": {
"type": "physical",
"color": [
1.0,
1.0,
1.0
],
"metallic": 1.0,
"roughness": 0.0
}
},
{
"type": "plane",
"point": [
0.0,
-0.5,
0.0
],
"normal": [
0.0,
1.0,
0.0
],
"material": {
"type": "physical",
"color": [
0.8,
0.8,
0.0
],
"metallic": 0.0,
"roughness": 1.0
}
}
]
}Each section (camera, render, lights, objects) is parsed by the SceneLoader class and automatically converted into C++ objects inside the engine.
- Anti-aliasing (Monte Carlo sampling) for smoother edges
- Depth of Field / Bokeh (simulate camera aperture)
- Global Illumination (indirect light bounces)
- Blinn–Phong model (specular highlights for glossy surfaces)
- Cook–Torrance model (microfacet BRDF for realistic metals)
- PBR Materials with roughness/metallic maps
- Clean graphical user interface (GUI) to adjust materials and camera in real time
- Live preview of scene updates
- Custom scene importer/exporter
- Configurable render settings via JSON or CLI
- Multithreading (OpenMP or std::thread)
- GPU acceleration (CUDA / OpenCL)
- Support for texture maps (diffuse, normal, roughness)
- Peter Shirley - Ray Tracing in One Weekend
- Ray Tracing by The Cherno
- Wikipedia - Ray Tracing
- Wikipedia - Path Tracing
- Wikipedia - Lambertian Reflectance
- Wikipedia - Specular Reflection
Author: Hetic Master CTO & Tech Lead 2026 - Lux Aeterna Year: 2025 - 2026 Project: Ray Tracer — Photorealistic Renderer in C++23