Cross-platform C++20 port of the popular JavaScript 3D library three.js r129.
The core library is mature and feature-complete, with advanced rendering capabilities including real-time path tracing on the WebGPU backend. It is usable for a wide variety of rendering applications, from interactive 3D apps to robotics and scientific visualisation.
The high-level API is mostly in line with three.js r129 with changes from newer revisions in some areas. The OpenGL backend is a mechanical port of the WebGL renderer. The WebGPU renderer is mostly at feature parity with the GL backend, but is not a direct port of the three.js WebGPU renderer.
You get a scene graph, materials, lighting, cameras, render loop, controls, loaders, all composable, in a handful of lines.
- Line, Points, Mesh, InstancedMesh
- Geometries [Box, Sphere, Plane, Cylindrical, Capsule, Tube, ++]
- Lights [Ambient, Directional, Point, Spot, Hemi, RectArea]
- Raycasting [Mesh, Line, Points]
- 2D/3D Textures, 2D/3D text, Sprites, RenderTarget, CubeMaps
- Transparency, Transmission, Shadows
- Environment maps, including PMREM
- Animation, Morphtargets, Bones
- Controls [Orbit, Fly, Drag, Transform]
- Water and Sky shaders
- Built-in text rendering and font loading [typeface.json, TTF]
- Built-in model loaders [Binary STL, OBJ/MTL, GLTF, COLLADA, USD, FBX, SVG, URDF]
- Basic Audio support using miniaudio
- Generic model loader based on Assimp
- Easy integration with Dear ImGui
- OpenGL 3.3 and WebGPU raster backends
- Real-time path tracing (on Vulkan backend)
Builds on Windows, Linux, MacOS, MinGW and with Emscripten.
And ROS2 users: threepp is a great fit for your visualisation needs.
Because C++ deserves nice things too.
Also, because fun.
threepp comes bundled with all required core dependencies.
Use CMake for project configuration and building.
Do note that you may also use a system installation of GLFW3 if you want or have issues with the bundled setup by passing
-DTHREEPP_USE_EXTERNAL_GLFW=ON to CMake.
cmake . -A x64 -B build -DCMAKE_BUILD_TYPE="Release"
cmake --build build --config "Release"cmake . -B build -DCMAKE_BUILD_TYPE="Release"
cmake --build buildPass to CMake:
-DCMAKE_TOOLCHAIN_FILE="[path to emscripten]\emsdk\upstream\emscripten\cmake\Modules\Platform\Emscripten.cmake"This will generate .html versions of a subset of the examples to be loaded in a browser.
You can run a collection of them online here.
When consuming threepp in your own application,
some headers will require additional dependencies to compile.
| Header | Dependency | Description |
|---|---|---|
| AssimpLoader | assimp | Import a wide variety of different 3D formats |
| ImguiContext | imgui | ImGUI utility |
In general, you'll find that math classes are value types, while threepp expect smart pointers for other types.
For convenience, geometries, materials, etc. have a static ::create function that returns a std::shared_ptr.
Thus, you don't necessarily need to handle memory explicitly using threepp.
Furthermore, materials, geometries and textures are automatically disposed of when they go out of scope.
Yay!
#include "threepp/threepp.hpp"
using namespace threepp;
auto createBox(const Vector3& pos, const Color& color) {
auto geometry = BoxGeometry::create();
auto material = MeshPhongMaterial::create();
material->color = color;
auto box = Mesh::create(geometry, material);
box->position.copy(pos);
return box;
}
auto createPlane() {
auto planeGeometry = PlaneGeometry::create(5, 5);
auto planeMaterial = MeshLambertMaterial::create();
planeMaterial->color = Color::gray;
planeMaterial->side = Side::Double;
auto plane = Mesh::create(planeGeometry, planeMaterial);
plane->position.y = -1;
plane->rotateX(math::degToRad(90));
return plane;
}
int main() {
Canvas canvas{"Demo"};
GLRenderer renderer{canvas};
auto scene = Scene::create();
auto camera = PerspectiveCamera::create(75, canvas.aspect(), 0.1f, 100.f);
camera->position.z = 5;
OrbitControls controls{*camera, canvas};
auto light = HemisphereLight::create();
scene->add(light);
auto plane = createPlane();
scene->add(plane);
auto group = Group::create();
group->add(createBox({-1, 0, 0}, Color::green));
group->add(createBox({1, 0, 0}, Color::red));
scene->add(group);
canvas.onWindowResize([&](WindowSize size) {
camera->aspect = size.aspect();
camera->updateProjectionMatrix();
renderer.setSize(size);
});
Clock clock;
canvas.animate([&] {
const auto dt = clock.getDelta();
group->rotation.y += 1.f * dt;
renderer.render(*scene, *camera);
});
}
Threepp is mainly available as a CMake package and can be consumed in a number of ways. It's also available as a Conan package, so it can be consumed using conan or xmake.
threepp is compatible with CMake's FetchContent:
include(FetchContent)
set(THREEPP_BUILD_TESTS OFF)
set(THREEPP_BUILD_EXAMPLES OFF)
FetchContent_Declare(
threepp
GIT_REPOSITORY https://github.com/markaren/threepp.git
GIT_TAG tag_or_branch # use a tag/branch (required for GIT_SHALLOW)
GIT_SHALLOW TRUE # fetch only the tip to keep the download small
)
FetchContent_MakeAvailable(threepp)
#...
target_link_libraries(main PUBLIC threepp::threepp)This is the preferred approach, as it enables users to update the targeted threepp version at will.
With THREEPP_BUILD_EXAMPLES and THREEPP_BUILD_TESTS off (as above), only the library is fetched. The example/test assets (models, textures, fonts, sounds, …) live in a separate threepp_data repository, fetched automatically only when examples or tests are enabled — library consumers never download them. For local development against a working copy of the assets, configure with -DFETCHCONTENT_SOURCE_DIR_THREEPP_DATA=/path/to/threepp_data.
Tip: Since threepp examples bundles imgui, you can link against it by including:
add_subdirectory("${threepp_SOURCE_DIR}/examples/external")
An example is provided here.
See also this demo, which additionally uses WxWidgets as the Window system.
Example conanfile.py :
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
class ExampleRecipe(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeDeps", "CMakeToolchain"
def requirements(self):
self.requires("threepp/0.0.20260310")
def layout(self):
cmake_layout(self)
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()Example xmake.lua file:
add_rules("mode.debug", "mode.release")
add_requires("imgui", {configs = {glfw_opengl3 = true}}) -- optional dependency for UI widgets
add_requires("assimp") -- optional dependency for importing assembly models (.glb/.dae)
add_requires("conan::threepp/0.0.20260310", {
alias = "threepp",
configs = {
settings = {"compiler.cppstd=20"}
}
})
target("example")
set_kind("binary")
add_files("src/*.cpp")
add_packages("imgui", "threepp", "assimp")
set_languages("c++20")












