A lightweight 3D graphics renderer written in C++, built from scratch without relying on modern GPU APIs such as OpenGL or DirectX.
This project demonstrates the core concepts of a rasterisation pipeline — including transformation matrices, barycentric interpolation, depth buffering, and texture mapping — implemented on the CPU.
- Model -> World -> View -> Projection transforms
- Perspective-correct barycentric interpolation
- Depth buffer (Z-buffer)
- Texture mapping
- Recursive Ray Tracing
- Hard & Soft shadows
- Mirror Reflection
- Metallic Surface (Perturbated Reflection)
- Glass / Water Refraction (Fresnel reflectance with Schlick approximation)
- Environment Map Sampling when no intersection
- Two-pass algorithm (Photon Emission & Storage -> Estimate Irradiance)
- Cosine-weighted hemisphere sampling for Photon Direction
- Caustic photon map for refractive caustics
- 3D KD-tree + K-Nearest Neighbour for queries
- Russian roulette termination depend on the material
- Free-flight movement
- Yaw / pitch rotation (Q/E + Z/C)
- Orbit modes about X and Y (O, X)
- Depth of field & bokeh via aperture sampling
- Adjustable focus distance and aperture size
- Spherical Point Source sampling with Uniform Distribution (Soft Shadow)
- Light Circular Motion (Orbit Light)
- Toggle background/environment reflections (
Nkey) - Uses Spherical Map for Environment Mapping
- Frame-by-frame PPM output
- Automatic folder clearing & naming
ffmpegpipeline for MP4 export- Light orbit & camera orbit animation presets
- Type: Opaque, Mirror, Metallic, Glass
- Reflectivity
- Tint
- Roughness
- Transparency
- Refractive Index
| Key | Action |
|---|---|
| ↑ / ↓ / ← / → | Move up / down / left / right |
| W / S | Move forward / backward |
| Key | Action |
|---|---|
| Q / E | Pan left / right |
| Z / C | Tilt up / down |
| Key | Action |
|---|---|
| I | Increase focus distance |
| U | Decrease focus distance |
| M | Increase aperture radius (stronger bokeh) |
| , | Decrease aperture radius (weaker bokeh) |
| Key | Action |
|---|---|
| H / L | Move light left / right |
| K / J | Move light up / down |
| G / ; | Move light forward / backward |
| P | Toggle light orbit |
| Key | Action |
|---|---|
| O | Toggle camera orbit about Y-axis |
| X | Toggle camera orbit about X-axis |
| F | Fly-through animation |
| T | Demonstration Sequence |
| B | Bokeh depth-of-field effect |
| Key | Action |
|---|---|
| N | Enable / disable environment map |
| Key | Action |
|---|---|
| R | Reset to Initial Camera and Light Position |
To enable Photon mapping, you need to alter the renderer.usePhotonMap flag in Renderer.cpp file
Some materials such as gold, mirror, and glass have very low diffuse values, so they are difficult to see without an environment map.
Press N to enable the environment map when testing these materials.
You can switch between materials by editing the usemtl tag inside the corresponding OBJ file:
usemtl gold_ball
usemtl mirror_ball
usemtl glass_ballgit clone git@github.com:<your_github_id>/Renderer.git
cd Renderer
make clean
make speedy # fast build (optimised) but buggyThe renderer supports per-frame recording for animations, camera orbits, fly-throughs, and bokeh demonstrations.
Firstly, set the desired title / feature / material you want to record, by changin the line
const std::string title = "<your_title>";Recording is triggered automatically in the rendering loop, if you want to enable recording undo these comment
clearDirectory(title, window);
size_t ppm_frame = 0;
record(ppm_frame, title, window);
ppm_frame++;If the folder already exists, it is cleared before a new recording begins.
If you want to end the recording, press ESC to stop the recording and exit the renderer.
Use ffmpeg to convert the PPM sequence into a video:
ffmpeg -framerate 30 -i frames/<your_title>/frame%04d.ppm -c:v libx264 -pix_fmt yuv420p <your_output>.mp4Now you will get a fresh recording of your desired features / material demonstration !!
© 2025 Gordon Wai Hin Kam. All rights reserved.
