A high-performance pathtracer using Vulkan compute shaders with JSON scene support and GLB import tools.
# Build the project
./build.sh
# Render a scene
./pathtracer demo
# Render with custom settings
./pathtracer demo --width 1920 --height 1080 --samples 200 --bounces 16The pathtracer uses a scene-based workflow:
# Render scene by name (looks in scenes/ directory)
./pathtracer <scene-name> [options]
# Examples:
./pathtracer demo # Render scenes/demo.json -> renders/demo.png
./pathtracer my-scene --samples 500 # High quality render
./pathtracer simple --width 800 --height 600Arguments:
scene-name: Name of scene file (without .json extension)--width <int>: Override image width--height <int>: Override image height--samples <int>: Override samples per pixel--bounces <int>: Override maximum ray bounces
Output: Images are saved to renders/<scene-name>.{png,ppm}
Scenes are defined in JSON format in the scenes/ directory. The format includes camera, sky, render settings, materials, and geometry:
{
"camera": {
"position": [0, 1, 3],
"pitch": -10,
"yaw": 180,
"fov": 45
},
"sky": {
"color": [0.5, 0.7, 1.0],
"brightness": 1.0
},
"render": {
"width": 800,
"height": 600,
"samples": 200,
"bounces": 12
},
"materials": [
{
"name": "red_diffuse",
"color": [0.9, 0.1, 0.1],
"emission": [0, 0, 0],
"roughness": 1.0,
"metallic": 0.0
},
{
"name": "chrome_metal",
"color": [0.98, 0.98, 0.98],
"emission": [0, 0, 0],
"roughness": 0.0,
"metallic": 1.0
},
{
"name": "light_source",
"color": [1.0, 1.0, 1.0],
"emission": [25, 20, 5],
"roughness": 0.0,
"metallic": 0.0
}
],
"spheres": [
{
"center": [0, 0, -1],
"radius": 0.5,
"material": 0,
"name": "red_sphere"
}
],
"triangles": [
{
"vertices": [
[-0.5, 0.5, -2],
[0.5, 0.5, -2],
[0, 1, -2]
],
"material": 1,
"name": "metal_triangle"
}
]
}position: Camera position in world spacepitch: Up/down rotation in degrees (negative = look down)yaw: Left/right rotation in degrees (0=+X, 90=+Z, 180=-X, 270=-Z)fov: Vertical field of view in degrees
color: Sky background color (RGB 0-1)brightness: Sky brightness multiplier
width,height: Output image resolutionsamples: Samples per pixel (higher = less noise)bounces: Maximum ray bounces (higher = more realistic lighting)
Note: Command-line arguments override scene render settings.
demo- Full feature demo (800x600, 200 samples)simple- Fast test scene (400x300, 50 samples)hd-demo- High quality scene (1920x1080, 1000 samples)
Convert GLB files to pathtracer scenes with full geometry and material extraction:
# Convert GLB to scene (run from main directory)
./convert-glb.sh model.glb my-scene
# Examples
./convert-glb.sh assets/car.glb car-scene
./convert-glb.sh downloads/house.glb house-sceneThis creates scenes/my-scene.json with:
- Extracted geometry: All triangles from GLB meshes
- Extracted materials: PBR materials converted to pathtracer format
- Optimal camera: Automatically positioned to view the model
- Smart scaling: Ground plane and lighting sized to model
- Full metadata: Model bounds, triangle count, material info
- Meshes: All triangle geometry (indexed and non-indexed)
- Materials: Base color, metallic, roughness, emission (scaled for pathtracer)
- Bounds: Automatic model sizing and camera positioning
- Naming: Preserves mesh and material names from GLB
The converter uses gltf-transform for robust GLB parsing:
- First run automatically installs dependencies via
npm install - Supports both
.glb(binary) and.gltf(text) formats - Handles complex meshes with multiple materials
- color: Base albedo color (RGB 0-1)
- emission: Light emission (RGB, values > 1 for bright lights)
- roughness: Surface roughness (0=mirror, 1=diffuse)
- metallic: Metallic behavior (0=dielectric, 1=metal)
// Diffuse materials
{"color": [0.9, 0.1, 0.1], "emission": [0,0,0], "roughness": 1.0, "metallic": 0.0}
// Metals (low roughness, high metallic)
{"color": [0.98, 0.98, 0.98], "emission": [0,0,0], "roughness": 0.05, "metallic": 1.0}
// Lights (emission > 0)
{"color": [1,1,1], "emission": [25, 20, 5], "roughness": 0.0, "metallic": 0.0}
// Rough metals
{"color": [0.8, 0.6, 0.3], "emission": [0,0,0], "roughness": 0.3, "metallic": 0.9}# Build and move executable to root
./build.sh
# Manual build (optional)
mkdir -p build && cd build
cmake ..
make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)- Vulkan SDK (1.3+)
- GLFW 3.3+
- CMake 3.16+
- C++17 compiler
macOS: brew install vulkan-sdk glfw cmake
Ubuntu: apt install vulkan-sdk libglfw3-dev cmake build-essential
Typical render times on Apple Silicon:
- 400x300, 50 samples: ~25ms
- 800x600, 200 samples: ~145ms
- 1920x1080, 1000 samples: ~2-5s
pathtracer/
├── pathtracer # Main executable
├── build.sh # Build script
├── scenes/ # Scene definitions (.json)
├── renders/ # Output images (.png/.ppm)
├── tools/ # GLB converter utilities
├── src/ # C++ source code
├── shaders/ # GLSL compute shaders
└── shaders_build/ # Compiled SPIR-V shaders