SkillAgentSearch skills...

Threepp

A cross-platform C++20 3D library with the high-level API of three.js

Install / Use

npx skills add markaren/threepp

Installs into whichever agent you are using.

README

threepp

Build License: MIT Conan Center

A cross-platform C++20 3D library with the high-level API of three.js — and modern backends: portable OpenGL, and a deferred Vulkan renderer with ray-traced accents.

On top of that: a scene editor, PhysX-backed robot simulation, and ground-truth sensor output for synthetic-data generation.

Real-time ray-traced FFT ocean Real-time FFT ocean — Vulkan deferred-hybrid renderer (raster-first, with ray-traced shadows & reflections) (examples/vulkan/vulkan_ocean.cpp)

The threepp scene editor The scene editor — hierarchy, inspector, Play mode, and a live sensor preview (apps/editor, doc/editor.md)

You get a scene graph, materials, lighting, cameras, render loop, controls, loaders, all composable, in a handful of lines.

📖 New here? Start with Getting started — a guide to the concepts the whole library is built from: the scene graph, ownership and lifetimes, geometry/material, lights, the frame loop, loaders and the two backends.

Highlights

Rendering

  • Two backends behind one scene graph: OpenGL 3.3 raster (the portable baseline, also the Emscripten/WebGL2 target) and a deferred Vulkan renderer (raster G-buffer with ray-traced AO, GI, reflections and shadows; denoised, with TAA).
  • Ocean — three-cascade FFT-displaced water with foam, transmission and live wind. Vulkan only; on OpenGL the type is an inert flat plane.
  • PMREM environment maps.
  • Gaussian splattingSplatCloud renders scans on both backends, with two loaders (INRIA .ply, PlayCanvas SOG) and dynamic LOD on Vulkan.

Simulation & perception

  • Ground-truth labels straight out of the render (Vulkan) — one call reads the G-buffer in its native format: float32 metric depth, per-object instance ids that survive add/remove/hide/LOD, semantic classes, world normals and motion. addView attaches N cameras rendered from one scene build in a single submission, so a whole sensor rig sees the same simulated instant.
  • Simulated sensors — LIDAR (VLP-16/HDL-32E/OS1-64/OS0-128 patterns), depth and event cameras, plus IMU, joint encoder, contact and 6-axis force/torque. Ray-traced on Vulkan, rasterized on OpenGL, with the same range semantics on both. Every measurement is seeded and sim-clock-stamped, so a recorded run replays bit-for-bit.
  • Robots, not just rigid bodies — PhysX reduced-coordinate articulations built from a URDF or xacro in one call, with joints, limits, PD drives, V-HACD concave colliders, and a header-only damped-least-squares IK solver. From C++ and Python.
  • Physical camera, lens and sensor model — EV100 exposure from an aperture/shutter/ISO triplet, photometric light units, OpenCV-convention intrinsics, Brown-Conrady and fisheye distortion applied to both the image and the labels, and electron-domain sensor noise. All off by default; it expects a scene lit in real photometric units.

Tooling

  • A scene editor and a headless player — author scenes with physics, sensors and Python behaviour scripts, then replay them in CI. Documents are plain three.js JSON, so an authored scene runs in an ordinary threepp program with no editor present.
  • Python bindings — the scene graph, headless render-to-NumPy, PhysX, and threepp.rl (a GPU-vectorized RL stack).
  • Built-in loaders — models [STL (binary & ASCII), OBJ/MTL, glTF/GLB incl. meshopt compression, COLLADA, SVG, URDF/xacro], images [PNG/JPEG, DDS, WebP, Radiance HDR, OpenEXR] and Gaussian-splat scans. USDLoader and FBXLoader are opt-in.
  • Native xacro support — URDF loading takes .urdf.xacro directly (macros, properties, YAML-driven parameters, $(find)/$(arg)), no ROS or Python install required; verified against the Franka and Universal Robots ROS 2 description.
  • Builds on Windows, Linux, macOS, MinGW and with Emscripten.

Current state of the project

Primary use case: research and education. threepp is built for research, prototyping, and learning — not as a production-hardened engine. API and behavioural stability are not prioritized: APIs may change, and backends (especially the Vulkan backend) evolve rapidly. Pin a tag/commit if you need reproducibility, and expect to track changes if you follow master.

There are two layers here, and they move at very different speeds.

The three.js port is mature and stable. The high-level API is mostly in line with three.js r129 with changes from newer revisions in some areas, and the OpenGL backend is a mechanical port of the WebGL renderer. It barely moves between releases, and it is what most users touch.

The simulation layer on top of it is where the project is going — the deferred Vulkan renderer, the sensor suite, PhysX robotics, the editor and the Python bindings. That is where the work goes, and it is what the stability warning above is really about.

A few limits worth knowing before you start:

  • The Vulkan backend evolves fastest and breaks most often. OpenGL is the conservative choice.
  • Gaussian splat clouds are a backdrop, not a simulation asset: they cast no shadows, appear in no reflection, contribute nothing to GI, are invisible to the ray-traced sensors, and are not serialized.
  • The editor is tested against OpenGL; its Vulkan view pane is best-effort. See the known-limitations list in doc/editor.md.
  • GPU code paths are not covered by CI — the runners have no device. Golden-image tests are a local pre-push check.

What works?

three.js parity — what the ported API gives you:

  • 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
  • Post-processing on the OpenGL path: EffectComposer with render/shader/mask/ clear/texture/save passes plus UnrealBloomPass and BokehPass (depth of field), MSAA-capable internal targets, and three.js addon shaders that port over as-is (examples/postprocessing)
  • Environment maps, including PMREM
  • Animation, morph targets, Bones
  • Controls [Orbit, Fly, Drag, Transform]
  • Water and Sky shaders
  • Built-in text rendering and font loading [typeface.json, TTF]
  • Scene serialization — ObjectExporter/ObjectLoader read and write three.js "Object" JSON (metadata 4.5) deterministically, with the option to reference source models and textures instead of inlining them. Documents authored by the three.js editor load as-is.

Beyond three.js — what this library adds:

  • Gaussian splatting — SplatCloud with two scan loaders and a Vulkan compute tile rasterizer (doc/vulkan_splats.md)
  • Simulated sensors — LIDAR, depth and event cameras, IMU, joint encoder, contact, force/torque
  • PhysX physics — rigid bodies, reduced-coordinate articulations, joints, soft bodies, vehicles, and V-HACD convex decomposition
  • Automatic mesh LOD (Vulkan, on by default), GPU occlusion culling, and NVIDIA DLSS / AMD FSR 3.1 temporal upscaling
  • Procedural content, all asset-free and first-party — quadtree-LOD terrain, trees, grass, conveyor systems, a parametric log cabin
  • Real-world terrain — a documented "region pack" format plus an included Python tool that builds one from Norwegian national open data (Kartverket elevation, NVDB roads, OSM footprints with building heights)
  • Basic Audio support using miniaudio
  • Generic model loader based on Assimp (requires the assimp package — see Optional downstream dependencies)
  • Easy integration with Dear ImGui

Applications

Two binaries build alongside the library (THREEPP_BUILD_EDITOR, on by default for a top-level GLFW build):

  • threepp_editor — a scene editor: viewport, hierarchy, inspector, undo/redo, and a Play mode backed by PhysX. Scenes save as ordinary three.js Object JSON with everything editor-specific (physics, sensors, scripts, joints, vehicles, splines, conveyors, sound) in userData, so a saved document opens and runs in a plain threepp program with no editor present. Python behaviour scripts attach to objects Unity-style. See doc/editor.md.
  • threepp_player — the same play runtime with no editing machinery: headless, independent episodes, sensor CSV recording, and a nonzero exit if any script raised or the document would not play. It registers the same play sessions the editor does, in the same order, so a scene that runs under Play runs in CI. See doc/player.md.

But, but why?

Because C++ deserves nice things too.

Also, because fun.

Implementation notes

In general, you'll find that math classes are value types, while threepp expects 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!

threepp/threepp.hpp is a convenience umbrella over the three.js-equivalent core. Every

Related Skills

View on GitHub
GitHub Stars862
CategoryDevelopment
Updated7m ago
Forks99

Languages

C++

Security Score

100/100

Audited on Aug 8, 2026

No findings