Tool

Render photorealistic 3D scenes with Monte Carlo path tracing

C++20 path tracer with Monte Carlo rendering, BVH acceleration, adaptive sampling, denoising, and Blender scene export for photorealistic 3D images.

Works with blender

Maintainer of this project? Claim this page to edit the listing.


91
Spark score
out of 100
Updated last month
Version 1.0.0

Add to Favorites

Why it matters

Generate high-quality photorealistic images from 3D scenes using physically-based rendering. Luz enables developers and artists to produce global illumination renders with advanced features like adaptive sampling, denoising, and atmospheric effects without external dependencies.

Outcomes

What it gets done

01

Trace light paths through 3D scenes with BVH-accelerated ray intersection

02

Export Blender scenes to custom format and render with multithreaded CPU

03

Denoise Monte Carlo renders using feature-buffer filtering techniques

04

Benchmark rendering performance with deterministic test harness

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/themartiano-luz | bash

Overview

Luz

Luz is a C++20 path tracer that renders images using Monte Carlo path tracing with global illumination. It accelerates rendering with BVH structures, supports adaptive per-pixel sampling, includes an NFOR-style denoiser, and ships with a Blender exporter that converts .blend scenes to Luz's custom .luz format. Use Luz when you need a C++20 path tracer with zero third-party dependencies that you can build on macOS, Linux, or Windows. It supports custom .luz scene files, CLI overrides for render parameters, and includes a deterministic benchmark harness. Use it when you want to export Blender scenes using the included Python script. Do NOT use Luz for real-time rendering or GPU-accelerated workflows - it is a multithreaded CPU renderer. Avoid it if you require production-ready support for complex Blender material nodes or industry-standard USD/Alembic pipelines.

What it does

Luz is a from-scratch C++20 path tracer that renders images using Monte Carlo path tracing with global illumination. It accelerates rendering with BVH structures, supports adaptive per-pixel sampling, includes an NFOR-style denoiser, and ships with a Blender exporter that converts .blend scenes to Luz's custom .luz format.

When to use - and when NOT to

Use Luz when you need a C++20 path tracer with zero third-party dependencies that you can build on macOS, Linux, or Windows. It supports custom .luz scene files, CLI overrides for render parameters, and includes a deterministic benchmark harness. Use it when you want to export Blender scenes using the included Python script.

Do NOT use Luz for real-time rendering or GPU-accelerated workflows - it is a multithreaded CPU renderer. Avoid it if you require production-ready support for complex Blender material nodes or industry-standard USD/Alembic pipelines, as the exporter has fidelity limits and the scene format is custom.

Inputs and outputs

You provide a .luz scene file (or export one from Blender using the included Python script) that defines geometry (spheres, planes, rectangles, triangles, cubes, volumes, OBJ meshes), materials (Lambertian, metal, dielectric, emissive, isotropic), lights (area, point, sphere, directional), and render parameters. You can override resolution, samples per pixel, adaptive sampling thresholds, max light bounces, threading, gamma correction, tone mapping, bloom, exposure, and contrast via CLI flags.

Luz outputs BMP and TIFF images. When you enable --denoise, it writes a separate denoised companion image. The benchmark harness provides render, denoise, post-process, and score breakdowns.

Integrations

Luz integrates with Blender via a Python exporter script that runs through Blender's command-line interface:

"/Applications/Blender.app/Contents/MacOS/Blender" -b scene.blend --python tools/blender_export_luz.py -- --output exports/scene.luz
./Luz --file exports/scene.luz --threads 8

The exporter writes .luz scene files plus OBJ meshes. OBJ mesh assets are resolved relative to the scene file, the current working directory, or the assets/objects/ folder.

Build systems supported: Make (primary on macOS/Linux), CMake 3.16+ (cross-platform, required on Windows with MSVC), and MinGW-based Makefile target for Windows. Python 3 is optional and only needed for tools and scripts.

Who it's for

Luz is for developers who want to work with a C++20 path tracer that has zero third-party dependencies. It includes a deterministic benchmark harness with per-stage breakdowns:

make benchmark BENCH_CPUS=1 BENCH_THREADS=1 > before.csv
make benchmark BENCH_CPUS=1 BENCH_THREADS=1 > after.csv
make benchmark-compare BEFORE=before.csv AFTER=after.csv

It is also for users who export Blender scenes and want control over sampling, denoising, and post-processing parameters. Unlike renderers with extensive plugin ecosystems, Luz offers a minimal codebase. Unlike GPU path tracers, it runs on any CPU with a C++20 compiler and scales across threads.

Source README

Luz

Luz is a C++20 Path Tracer developed from scratch with zero third-party dependencies.

It supports Monte Carlo path tracing, global illumination, BVH acceleration, adaptive sampling, denoising, atmospheric scattering, custom scene files, and a Blender-to-Luz exporter.

Features

  • Monte Carlo path tracing
  • Global illumination
  • Multithreaded CPU rendering
  • Adaptive sampling
  • Denoiser (NFOR-style)
  • Spheres, planes, rectangles, triangles, cubes, volumes, and OBJ meshes
  • Lambertian, metal, dielectric, emissive, and isotropic materials
  • Area, point, sphere and directional lights
  • Custom .luz scene files
  • .blend to .luz converter
  • Fully customizable render parameters via CLI or scene file
  • Importance sampling with PDFs
  • BVH acceleration, including packed mesh BVHs with binned SAH construction and near-first traversal
  • Atmospheric simulation w/ scattering
  • Depth of field, antialiasing, exposure, contrast, tone mapping, gamma correction, and bloom
  • BMP and TIFF output
  • Deterministic benchmark harness with render, denoise, post-process, and score breakdowns

Requirements

  • C++20 compiler
  • Make or CMake 3.16+
  • Python 3, only for optional tools/scripts

Quick Start

Build with the Makefile:

make

Render a bundled example scene:

./Luz --file examples/scenes/blender_monkey.luz --samples 50 --resolution 300x300

The default output is render.bmp. Scene files can set outputfilename=..., and the CLI can override common render settings.

Run the test suite:

make test

Benchmarking

Luz includes deterministic benchmarks for render, denoise, post-process, and
overall score comparisons.

make benchmark BENCH_CPUS=1 BENCH_THREADS=1 > before.csv
make benchmark BENCH_CPUS=1 BENCH_THREADS=1 > after.csv
make benchmark-compare BEFORE=before.csv AFTER=after.csv

For details, see docs/benchmarks.md.

CMake

A CMake build is also available:

cmake -S . -B build
cmake --build build
ctest --test-dir build

Platform Support

Supported platforms:

  • macOS
  • Linux
  • Windows

On macOS and Linux, the Makefile is the primary path. On Windows, use CMake with
MSVC or the MinGW-based Makefile target:

make windows

WSL is also supported as a Linux build environment.

Build Optimizations

Release builds are tuned for the machine doing the build by default. The
Makefile enables -O3, native CPU tuning with -march=native, and link-time
optimization with -flto. It also enables a fast floating-point mode where the
compiler/platform supports it. CMake uses the same release intent: -O3, native
CPU tuning, and interprocedural optimization/LTO when supported.

These defaults produce faster local renders, but binaries built with
-march=native may not run on older or different CPUs, and LTO can expose
toolchain-specific linker issues. If you hit an illegal-instruction crash,
linker error, or need a more portable binary, disable the aggressive options and
rebuild from clean objects:

make clean
make NATIVE=0 LTO=0

For CMake builds, configure with the optimization toggles off:

cmake -S . -B build -DLUZ_NATIVE_OPTIMIZATIONS=OFF -DLUZ_ENABLE_LTO=OFF
cmake --build build --clean-first

CLI

Usage: ./Luz [options]

  -f, --file PATH             Load a .luz scene file
  -r, --resolution WxH        Override render resolution
  -s, --samples N             Override samples per pixel
  --adaptive [true|false]     Enable adaptive per-pixel sampling
  --no-adaptive               Disable adaptive sampling
  --adaptive-min-samples N    Minimum samples before adaptive stopping
  --adaptive-threshold F      Relative adaptive noise threshold
  --adaptive-check-interval N Adaptive convergence check interval
  -mlb, --maxLightBounces N   Override maximum light bounces
      --max-light-bounces N   Alias for --maxLightBounces
  -t, --threads N             Render with N worker threads
  --seed N                    Seed random sampling
  --gamma true|false          Toggle gamma correction
  -tm, --tonemapping true|false  Toggle tone mapping
  --bloom true|false          Toggle bloom
  --exposure EV              Exposure compensation in stops
  --contrast F               Display contrast multiplier
  --denoise [true|false]      Write a denoised companion render
  --no-denoise                Disable denoising
  -o, --output PATH           Override render output path
  --denoise-output PATH       Override denoised output path
  --render-times              Write renderTime.bmp
  --benchmark                 Run the built-in benchmark scene
  --benchmark-case NAME       Benchmark case: default, many-objects, mesh-bvh, diffuse, postprocess, atmosphere, lights, emissive-geometry, primitives-materials, volumes, obj-mesh

Adaptive Sampling

--adaptive treats --samples as the maximum samples per pixel. Each pixel
uses a progressive per-pixel sample sequence, renders at least
--adaptive-min-samples, then periodically checks luminance and RGB confidence
intervals. Very dark pixels use a conservative minimum before they can stop, so
rare light contributions are less likely to be mistaken for converged black.

Lower thresholds keep more detail and cost more time. For final renders, start
with a high max sample count and tune with values like:

./Luz --file exports/stormtroopers.luz --samples 4096 --adaptive --adaptive-min-samples 512 --adaptive-check-interval 64 --adaptive-threshold 0.005 --denoise

Denoising

--denoise enables Luz's NFOR-style feature-buffer denoiser and writes a
separate companion image. By default, render.bmp becomes
render_denoised.bmp; use --denoise-output PATH to choose the exact path.

The denoiser has no hard minimum resolution or sample count, but it needs enough
signal to estimate useful color and feature statistics. One sample per pixel is
mainly a stress test: there is no per-pixel variance estimate, so the denoised
image can look almost unchanged or can smooth the wrong details. Use at least a
few samples per pixel for previews, and prefer roughly 16+ samples per pixel
when judging denoiser quality. Very low resolutions also make evaluation
misleading because each local filter window covers too much of the image.

Scene Files

Example scenes live in examples/scenes/. Mesh assets live in assets/objects/. The scene-file format is documented in docs/scene-files.md.

Object paths in .luz files are resolved relative to the scene file first, then relative to the current working directory, then under assets/objects/. This means examples/scenes/blender_monkey.luz can reference ../../assets/objects/blender_monkey.obj and still run from the repository root.

OBJ meshes can also be offset and assigned a scene material:

obj=mesh.obj,(x,y,z),material[
metal=(0.8,0.8,0.8),0.1
]

Blender Exporter

Blender scenes can be exported through Blender's Python API:

"/Applications/Blender.app/Contents/MacOS/Blender" -b scene.blend --python tools/blender_export_luz.py -- --output exports/scene.luz
./Luz --file exports/scene.luz --threads 8

The exporter writes a .luz file plus OBJ meshes. Usage and current fidelity
limits are documented in docs/blender-exporter.md.

Repository Layout

include/luz/       Public headers
src/core/          Math, geometry, materials, image, and sampling code
src/renderer/      Rendering implementation
src/scene/         Scene model and scene helpers
src/io/            Scene-file, OBJ, BMP, and TIFF loading/writing
src/cli/           Command-line entry point and flags
examples/scenes/   Example .luz scene files
assets/objects/    OBJ assets used by examples
docs/images/       Compressed showcase images
tools/             Export and utility scripts
tests/             Standard-library-only test program
docker/            Benchmark container

Showcase

Personal Note

Special thanks to the Ray Tracing in One Weekend book series. It was a great source of inspiration and information during a big part of the development of Luz, specially since those were times before AI.

Attribution

Stormtrooper Scene by @ScottGraham on BlendSwap.

Bust Statue by @geoffreymarchal on BlendSwap.

Discussion

Questions & comments ยท 0

Sign In Sign in to leave a comment.