A Neural Radiance Field in C++ and LibTorch. Takes images of a static scene with known camera poses, fits a radiance field, and renders RGB and depth from new viewpoints.
![]() |
![]() |
|---|---|
| RGB | Depth |
Under 1000 lines of C++ implementing a NeRF end to end: ray generation, Fourier positional encoding, a SIREN network, hierarchical sampling with a proposal network, volume rendering, and PSNR/SSIM evaluation. No framework abstraction, no Python in the training loop. The whole pipeline is small enough to step through in a debugger.
The scope is narrow:
transforms.json documented in docs/usage.md.For state-of-the-art quality or speed use nerfstudio or instant-ngp. This repo is for reading the algorithm.
On the NeRF synthetic scenes at 160×160 it reaches 25.1 PSNR / 0.90 SSIM on lego over 13 held-out views. Full numbers and method in docs/internals.md.
Everything the build needs — compiler, CMake, LibTorch, nlohmann_json, and ImageMagick for the GIFs — comes from one conda environment. A CUDA GPU is strongly recommended.
1. Create the environment.
git clone https://github.com/Bharath2/NeRF.cpp
cd NeRF.cpp
conda env create -f environment.yml
conda activate nerfcpp
That installs a CUDA 13 LibTorch, which needs an NVIDIA driver 580 or newer; on an older
driver, environment.yml says which two values to change. With no GPU at all, comment out
the six CUDA lines and uncomment the single cpu_mkl line before creating the
environment.
2. Build. CMake picks up LibTorch and nlohmann_json from the active environment, so there is nothing to configure:
cmake -B build
cmake --build build -j
3. Train on the bundled lego scene. A 100-frame copy of the NeRF synthetic lego
scene ships in data/lego, so you can run immediately:
./build/NeRF.cpp data/lego output_lego
Start with a short run to confirm everything works before committing to the full 10,000 iterations:
./build/NeRF.cpp data/lego output_lego --iters 200 --size 64
Checkpoints, preview renders and metrics land in the output directory. Every 8th view is held out and never trained on, so the metrics are measured on unseen data.
4. Turn the frames into GIFs (ImageMagick, already in the conda environment):
bash scripts/make_gifs.sh output_lego 30 10000 100 5
To rebuild the GIFs later without retraining, point RENDER_DATA at the scene and the
orbit is re-rendered from checkpoint.pt first:
RENDER_DATA=data/lego bash scripts/make_gifs.sh output_lego 30 10000 100 5
--help lists every setting; none of them require a rebuild.
transforms.json format, camera pose conventions, the full flag reference, output
files, and troubleshooting.Issues and pull requests are welcome. Results on scenes outside the synthetic dataset would be useful. If you train it on something interesting, open an issue with the renders.
BSD 3-Clause. If you use it in academic work, there is a CITATION.cff.