A 3D game engine written in Mojo.

Cinder 0.1.0 runs on Mojo 1.2.0 over a single C11 shim around wgpu-native, SDL3, Jolt, miniaudio, cgltf, KTX-Software, meshoptimizer, Dear ImGui and Tracy. It has a clustered forward+ renderer, an archetype ECS, physics, skeletal animation, 3D audio, tools and a playable sample game, all verified on Linux x86-64.

Apache-2.0 · engine commit 47c9352 · docs imported 2026-11-09

The Cinder sample game's arena level: a yellow character casting a shadow on a grey floor, a green collectable beside it, a wall of crates behind.
sample game · arena · rendered headless on Mesa lavapipe · 800×500

Where it stands

Straight from the engine's deliverable report and changelog. Nothing here is claimed beyond what those record.

Linux x86-64

Built and tested

45 test programs pass (2026-11-09). Three consecutive full test runs, identical results, no flakes, also under ASan and UBSan where noted, on X11 and Wayland for the windowed tests.

Test results

macOS arm64

Not built yet

A declared target with the Metal surface path written, but it has not been built or run: no Apple Silicon machine or runner was available. Every phase gate is half open until it is.

Blockers

Performance

Measured on a software rasteriser only

The only GPU available was Mesa lavapipe, which renders on the CPU. Budgets are recorded there as regression baselines, not met on reference hardware.

How it is measured

The stack

Mojo above, C below, one flat C11 ABI between them. Every C callback writes fixed-size events into lock-free rings that Mojo drains once per frame on the main thread, so Mojo never runs on a C thread. Bindings are generated and checked field by field against the C compiler.

  1. sample/ and your gamea Game run by the App
  2. cinder/app · cinder/toolsruntime, fixed-step loop, headless mode, debug overlay
  3. render physics anim audio input assets scenethe subsystems
  4. cinder/ecs · cinder/gfx · cinder/platformarchetype ECS, typed wgpu layer, SDL3
  5. cinder/coremath, jobs, handles, arenas, log, profile
  6. cinder/ffigenerated bindings, layout-tested
  7. libcinder_nativethe C11 shim and vendored libraries

Architecture · Threading model · Decision records

Native dependencies and pinned versions
LibraryRolePin
Mojothe engine language1.2.0 (build 2016d0cd)
wgpu-nativeWebGPU over Vulkan (Metal declared), shaders in WGSLv29.0.1.1 (webgpu-headers 673658b)
SDL3windows, input, gamepads, surfacesrelease-3.4.20
Jolt Physicsrigid bodies and CharacterVirtual, through joltc2bbcf73 / v5.6.0
cgltfglTF 2.0 importv1.15
KTX-SoftwareKTX2 textures, BasisU ETC1S/UASTC, BC7 transcodesee report
meshoptimizermesh optimisation and LODssee report
miniaudiobuses, streams, 3D audio0.11.26
Dear ImGuidebug overlay, through Dear Bindingsv1.93.0-docking / v0.27
Tracyprofiling zones, started on demandsee report

Subsystems

Each has a guide (ownership, setup, threading rules, pitfalls) and an API reference generated from its docstrings: 1306 symbols in all.

The sample game

A third-person collect-them-all built only on public engine APIs: a skeletal character on the character controller with an idle, walk and run blend tree, arena and Sponza levels, 32 orbiting shadowed point lights plus a sun and IBL, 500+ dynamic crates, 3D effects and music on buses, a pause menu with saved settings and rebindable keys, save and load, and an autopilot that tests and benchmarks drive headless.

bash
tools/in_container.sh pixi run sample                    # windowed: WASD/Space, Esc for the menu
tools/in_container.sh pixi run sample -- --level sponza  # the Khronos atrium
tools/in_container.sh pixi run sample-headless           # offscreen autopilot run

Entry point source · ADR-0014

Arena level: the KayKit character on the Jolt character controller, shadowed by the sun, crates behind.
Arena level: the KayKit character on the Jolt character controller, shadowed by the sun, crates behind.
Sponza level: the Khronos atrium with a mesh collider, lit by orbiting point lights and IBL.
Sponza level: the Khronos atrium with a mesh collider, lit by orbiting point lights and IBL.
Sponza level, mid-hall.
Sponza level, mid-hall.

All screenshots are real engine output, rendered headless on Mesa lavapipe at 800×500.

Renderer, checked by golden images

16 Khronos glTF models pass golden-image tests (SSIM >= 0.985), under 4x MSAA, AgX, bloom, GTAO, cascaded sun shadows and a procedural sky IBL. These are the committed Linux references, each reviewed against Khronos's own render.Render validation

Your first game in an hour

The tutorial builds a red ball you push around a lit ledge to knock six crates off the edge. Every snippet is real: the finished code lives inexamples/first_game/ and a test compiles it and runs it headless.

  1. Prerequisites
  2. An App and a Game
  3. A ledge, crates and a ball
  4. A sun and a camera
  5. Input as actions and axes
  6. Pushing the ball: the fixed step
  7. Per-frame logic
  8. A HUD
  9. Cleaning up
  10. Running it headless, and testing it

Start the tutorial

mojo
var config = AppConfig(String("First game"), 1280, 720, False)
config.audio = False
var rest = parse_app_args(args, config)
var app = App(config^)
var game = FirstGame()
while app.run_frame(game):
    frames += 1
    if max_frames >= 0 and frames >= max_frames:
        break
game.shutdown(app)
_ = game^
_ = app^

The whole entry point loop: parse engine options, build the App, run frames, then end the game before the app.

Benchmarks, honestly

Reference hardware (an RTX 3060-class Linux machine and an Apple M2) was not available. Every number below comes from Mesa lavapipe rendering 1080p on the CPU inside Docker, and serves as a regression baseline with a 10% gate, not as a statement about the GPU budgets.

Budgets and measurements
BudgetMeasured (lavapipe host)Status
Sample p99 ≤ 16.6 ms at 1080p high294.6 ms median, 356.9 ms p99 (CPU rasterised)Unmeasured on reference hardware
Stress scene ≥ 60 fps (50k instances, 2,000 bodies, 256 lights)721.3 ms median, 785.0 ms p99 (CPU rasterised)Unmeasured on reference hardware
Physics step ≤ 4 ms, 2,000 bodies0.73 ms median, 2.34 ms p99Met on this CPU
Cold start ≤ 2 sstress 0.97 s, sample arena 1.55 s; Sponza above 2 sMet for arena and stress; Sponza not met
Zero allocations per steady-state frame0 Mojo allocations over 60 framesMet, asserted by a test
Mojo ECS within 10% of flecsratios 0.91, 1.00, 0.98 over three runsMet; the Mojo ECS is kept

Full benchmark results · Method

Documentation built for AI agents

Mojo moved fast between 1.0 and 1.2, so models misremember it. Cinder's docs ship in forms an agent can load directly, plus a brief that tells it what the engine's own notes learned the hard way.

Using Cinder with AI coding agents