bvh: A Header Only BVH Construction and Traversal Library for C++
A modern C++ BVH construction and traversal library
At a glance
- What is it?
- The bvh library is a small, standalone, MIT licensed C++ library for building and traversing bounding volume hierarchies, with four construction strategies from a single threaded sweeping SAH builder to a multithreaded mini-tree builder, careful traversal, serialization, and a C API. It depends on nothing but the standard library.
- Who is it for?
- bvh fits a renderer or geometry tool that needs a bounding volume hierarchy it can read, modify and embed without pulling in a full ray tracing framework, and that wants to choose between build strategies per scene instead of accepting one default.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A Small Library With a Choice of Builders
The bvh library is described as a small, standalone library for BVH construction and traversal, and it is written in C++ under the MIT licence. The word standalone is the design statement, because the dependency policy in the second version is explicit: it only depends on the standard library, with parallelisation using a custom thread pool based on std::thread.
That is a meaningful constraint for a rendering library, since the usual choice is to use an existing job system, and it means the library can be dropped into a codebase that already has its own threading model without a conflict.
The API comes in two layers. There is a low-level API with direct access to the various builders, and there is a high-level DefaultBuilder API which selects the best builder depending on the desired BVH quality level. That split lets a caller make the trade-off explicitly, per scene, rather than accepting whatever the library's default happens to be.
The scope has also widened in the second version. The library now supports a variable amount of dimensions, with 2D, 3D and 4D BVHs, and different scalar types such as float or double. That matters for anyone doing 2D spatial queries, which are common in collision and culling code and are awkward to express in a library that hard codes three dimensions and floats.
The repository layout is correspondingly small: src/, test/, cmake/, a CMakeLists.txt, the README, the performance chart and the rendered example image.
Four Builders With Different Costs
The construction strategies are the heart of the library, and each one is tied to a paper, which tells you what problem it solves.
The high-quality, single-threaded sweeping SAH builder is the one to reach for when the build time does not matter and the tree quality does. Sweeping is the classic surface area heuristic approach, and the quality it produces is the reference the others are measured against.
The fast, medium-quality, single-threaded binned SAH builder is inspired by On Fast Construction of SAH-based Bounding Volume Hierarchies by I. Wald. Binning trades exactness for speed, and the quality is medium rather than high, which is the usual trade for a build that has to happen on every asset change.
The fast, high-quality, multithreaded mini-tree BVH builder is inspired by Rapid Bounding Volume Hierarchy Generation using Mini Trees by P. Ganestam and colleagues. The mini-tree approach builds local trees that are then merged, and that is what makes it both fast and high quality, and the multithreading is what makes it fast on a machine with cores.
The reinsertion optimizer is based on Parallel Reinsertion for Bounding Volume Hierarchy Optimization by D. Meister and J. Bittner, and it is a separate pass rather than a builder, so it can be applied after a fast build to improve it.
So the practical menu is: build fast and accept medium quality, build fast and high quality with multiple cores, build slowly and get the best tree, or build fast and then optimise it afterwards.
DefaultBuilder: One Call, Chosen by Quality Level
The high-level entry point is DefaultBuilder, and its job is to remove the need to make that choice yourself.
It selects the best builder depending on the desired BVH quality level, which means the caller states an intent rather than a strategy. The code is shorter, the trade-off is expressed in the level you ask for, and the library is free to change which builder backs a given level in a later version.
For most projects that is the right way in. The low-level API is there for the cases where the default is wrong, and the README lists it as a separate feature, direct access to various builders.
The two APIs are what make the library usable at two scales. A renderer that wants a quick tree for a preview and an optimal tree for the final frame can use the low-level API twice, once per case, and the same traversal code works for both. An application that just wants a working hierarchy asks DefaultBuilder for a level and gets on with it.
The reinsertion optimizer being a separate pass is worth noting in this context, since it means the fast builder and the optimiser compose, and the composed result is a different quality level from either alone. Whether the DefaultBuilder exposes that combination, and at which level, is not stated in the README, so it is a question to put to the project if it matters to you.
Traversal: Robust Ordering and a Shadow Ray Heuristic
The traversal side is where a naive BVH implementation loses most of its time, and the library takes its algorithms from published work.
The core traversal algorithm is described as fast and safe, and it is based on the paper Robust BVH Ray Traversal by T. Ize. That reliability matters because the classic failure mode of a BVH traversal is numerical: a ray that grazes a triangle edge produces floating point differences between the two implementations of the same intersection test, and a traversal that assumes consistent ordering ends up traversing the wrong side of a node. A traversal built to tolerate that avoids the infinite loop and the missed hit that a fragile one can produce on exactly the geometry you least want to get wrong.
The ray and primitive intersection routines are also from the literature. The ray-triangle intersection is based on Fast, Minimum Storage Ray/Triangle Intersection by T. Möller and B. Trumbore, and there is a fast ray-sphere intersection routine.
The new addition in the second version is a surface area traversal order heuristic for shadow rays, based on SATO: Surface Area Traversal Order for Shadow Ray Tracing by J. Nah and D. Manocha. Shadow rays are the case where the traversal order matters most, because a shadow ray usually hits something early and the goal is to reach that hit as fast as possible, so a dedicated ordering heuristic for them is a real improvement rather than a detail.
Together these mean the library is not a teaching implementation of BVH, it is a set of carefully chosen algorithms assembled into something you can use in a renderer.
Header Only, Standard Library Only, and a C API
The build model is deliberately minimal. The library is header-only, and it depends on nothing but the standard library, with its own thread pool built on std::thread rather than on an external job system.
The consequence is that integrating it is a matter of adding the sources to your project, and the CMake route is the documented one. You clone or add the repository as a submodule, for instance into contrib/bvh, and add two lines to your CMakeLists.txt:
add_subdirectory(contrib/bvh)
target_link_library(my_project PUBLIC bvh)The C API is the second new feature in the second version, and it exists for two stated reasons. The bindings are not enabled by default, and are built by configuring CMake with -DBVH_BUILD_C_API=ON. And if the intent is to use the library in a pure C environment which does not have the C++ standard library as a dependency, it might be a good idea to statically link the C++ standard library, which is done by adding -DBVH_STATIC_LINK_STDLIB_C_API=ON to the CMake command line.
That combination, a C API plus a statically linked standard library, is what makes the library usable from a C project, from a language binding, or from a plugin host that does not want to pull a C++ runtime into the host process. The example in the test directory, test/c_api_example.c, shows how the bindings are used.
The other new feature is a serialization and deserialization interface, with a worked example in test/serialize.cpp that saves a BVH to a file and loads it back, which saves the build time on a scene that has not changed.
Version 2, the Examples and How to Judge It
The README opens with a note that this is the second version of the library and that the v1 branch holds the older, first version. So there is a maintained v2 and a preserved v1, and the changes between them are marked in the feature list with a NEW tag, which makes the upgrade visible at a glance.
The changes in version 2 are the C++20 interface using std::span instead of raw pointers, the high-level DefaultBuilder API, the shadow ray traversal order heuristic, the serialization and deserialization interface, the variable dimensions and scalar types, the standard library only dependency, and the C API.
The examples are kept up to date with the API, and there are four of them. A basic example at test/simple_example.cpp traces one ray on a scene made of a couple of triangles. A benchmarking utility at test/benchmark.cpp showcases what the library can do. A serialization test at test/serialize.cpp shows how to save and load a BVH from a file. And a C API example at test/c_api_example.c shows how to use the C bindings.
To build the examples, the README gives a short sequence:
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=<Debug|Release> -DENABLE_TESTING=ON
cmake --build .The last thing to weigh is the performance comparison. The README compares the library with Embree, Fast-BVH and nanort and publishes a chart, and the example render at the top of the README was produced by a path tracer using this library, on a scene from Blend Swap distributed under CC-BY 3.0. Read the chart before you commit, because the library positions itself against production ray tracing kernels, and knowing where it sits relative to Embree tells you whether it is the right tool for your renderer or whether you need the heavyweight option. The project publishes no GitHub releases, so the repository is the distribution, and the last push was on 2026-10-16.
Editorial conclusion
bvh fits a renderer or geometry tool that needs a bounding volume hierarchy it can read, modify and embed without pulling in a full ray tracing framework, and that wants to choose between build strategies per scene instead of accepting one default. It is a poor fit if you want the last few percent of ray tracing throughput, since the README compares the library against Embree, nanort and Fast-BVH with a chart, and it is the wrong choice if you need a maintained package from a registry, since the project publishes no GitHub releases and is consumed as a git submodule. Before adopting it, check the C++20 requirement, because the interface uses std::span instead of raw pointers, and read the chart to see where this library sits against the alternatives. It is MIT licensed and the last push was on 2026-10-16.
Frequently asked questions
What is the bvh library and what does it provide?
It is a small, standalone, MIT licensed C++ library for BVH construction and traversal. It offers a low-level API with direct access to the builders, a high-level DefaultBuilder API that selects a builder by quality level, reliable traversal, serialization, support for 2D, 3D and 4D hierarchies with float or double scalars, and a C API.
Which BVH construction algorithms does the library implement?
A single-threaded sweeping SAH builder, a fast medium-quality single-threaded binned SAH builder inspired by Wald, a fast high-quality multithreaded mini-tree builder inspired by Ganestam and colleagues, and a reinsertion optimizer based on Parallel Reinsertion for BVH Optimization by Meister and Bittner.
How do I add the bvh library to my CMake project?
The library is header-only. Clone or add the repository as a submodule, for instance into contrib/bvh, then add `add_subdirectory(contrib/bvh)` and `target_link_library(my_project PUBLIC bvh)` to your CMakeLists.txt.
Does the library depend on anything outside the C++ standard library?
No. In the second version it only depends on the standard library, with parallelisation using a custom thread pool based on std::thread. The optional C API is built with -DBVH_BUILD_C_API=ON, and -DBVH_STATIC_LINK_STDLIB_C_API=ON statically links the C++ standard library for pure C environments.
How does bvh compare with other BVH libraries?
The README publishes a performance comparison with Embree, Fast-BVH and nanort in a chart, and the example render was produced by a path tracer using this library. The project is on its second version, with the first kept in the v1 branch.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/madmann91-bvh)Was this useful?