Three.js and Rapier, already wired up.
Renderoni is an open-source 3D web game engine. It wires Three.js and Rapier into a fixed game loop with player controls, headless tests, and tools for coding agents.
🕹️ Play the console OS • 🚀 Quickstart • 🤖 MCP Agent Tools
Install the beta release. (Note: npm package is not yet published in this repo worktree, so consider these commands the beta release contract).
npm install renderoni@beta three @dimforge/rapier3d-compatWhen a stable 1.0 release is published, the future stable install command will be npm install renderoni three @dimforge/rapier3d-compat.
Here's how you spawn a player, a floor, and a coin in a real browser:
import { createRenderoni } from 'renderoni';
import { body, kccPlayer, light, sensor } from 'renderoni/presets';
const canvas = document.querySelector<HTMLCanvasElement>('#game');
if (!canvas) throw new Error('Expected <canvas id="game">');
const game = await createRenderoni({
mode: 'interactive',
canvas,
seed: 42,
});
game.add(light({ type: 'directional', position: [20, 40, 20] }));
game.add(body({ shape: 'box', type: 'fixed', size: [100, 1, 100], position: [0, -0.5, 0] }));
const player = game.add(kccPlayer({ id: 'hero', position: [0, 1, 0], moveSpeed: 6.5 }));
game.add(sensor({ id: 'coin', position: [3, 1, 0] }));
const resize = () => {
const width = canvas.clientWidth;
const height = canvas.clientHeight;
if (game.native.renderer) {
game.native.renderer.setSize(width, height, false);
}
game.native.camera.aspect = width / height;
game.native.camera.updateProjectionMatrix();
};
new ResizeObserver(resize).observe(canvas);
resize();
game.start();You can run that exact same game headlessly in Vitest. No browser, no visual regression screenshots, just deterministic physics and game logic running in Node.js.
import { expect, test } from 'vitest';
import { createRenderoni } from 'renderoni';
import { body, kccPlayer, sensor } from 'renderoni/presets';
import 'renderoni/testing/matchers';
test('player collects coin', async () => {
const game = await createRenderoni({ mode: 'headless', seed: 42 });
game.add(body({ shape: 'box', type: 'fixed', size: [100, 1, 100], position: [0, -0.5, 0] }));
const hero = game.add(kccPlayer({ id: 'hero', position: [0, 1, 0] }));
game.add(sensor({ id: 'coin', position: [3, 1, 0] }));
hero.actions.move({ x: 1, z: 0 });
game.step(60);
expect(game).toHaveTick(60);
expect(hero.position[0]).toBeGreaterThan(1.5);
expect(game).toHavePassedDiagnostics();
});If you've ever built a game in Three.js, you know rendering is just the first step. Renderoni solves the boilerplate:
- Three.js + Rapier Sync: Visuals and physics transforms interpolate perfectly.
- Deterministic Scope: Fixed ticks, seeded PRNG, and quantized state hashing. Run it twice, get the same result.
- Useful Presets: Players, rigid bodies, sensors, lights.
- Headless Node.js Testing: Run full physics and game logic in Vitest.
- AI-Agent Ready: Built-in stdio MCP server for agent tooling.
- Native Escape Hatches: Direct access to
game.native.scene,.camera, and.worldwhen you need standard Three/Rapier features.
Renderoni is currently in 0.9.0-beta.1. Here is exactly what works today and what is coming post-1.0.
| Feature | Status | Notes |
|---|---|---|
| Engine Core (Ticks, PRNG) | 🟢 Stable Beta | Exact run-to-run hashes on the pinned matrix. |
| Physics Sync | 🟢 Stable Beta | Dual-buffer interpolation. |
| Audio Events | 🟡 Preview | Records and emits sound events. Connect your own playback. |
| VFX Triggers | 🟡 Preview | Screen shake and VFX event hooks. Rendered particles are planned. |
| Model Studio | 🟡 Preview | Local notes/screenshots/JSON export only. No project persistence. |
| Networking / SSE | 🔴 Post-1.0 | Removed until stable release. |
| Gamepads | 🔴 Post-1.0 | Keyboards, mice, and touch only right now. |
| Bloom / GPU Particles | 🔴 Post-1.0 | Not available yet. |
Connect Claude Desktop, Antigravity, Cursor, or any MCP client directly to your game. Renderoni uses a stdio MCP server (no network required).
To start the MCP server:
npx renderoni@beta mcpThe server exposes five tools for coding agents:
-
describe: Inspect engine configuration, active entities, and registered actions. -
observe: Get a Tier 0 Markdown summary (at most 500 bytes) of positions, tags, state, and recent events. -
act: Dispatch typed gameplay actions ({ name, payload }). -
step: Advance the simulation by$N$ fixed ticks. -
check: Run AST assertions against the engine state.
Don't have your coding agent write giant scene graphs. Use a concise SceneInventory JSON, build objects with img2threejs, and mount them.
import { createRenderoni } from 'renderoni';
import { kccPlayer, light } from 'renderoni/presets';
import { mountSceneInventory, type SceneInventory } from 'renderoni/scene';
const inventory: SceneInventory = {
version: 1,
prompt: 'stone courtyard with a crate and a coin',
elements: [
{ id: 'crate', factory: 'woodCrate', kind: 'prop', position: [0, 0.5, 0], collider: { shape: 'box', size: [1, 1, 1] } },
],
};
const game = await createRenderoni({ mode: 'headless', seed: 42 });
game.add(light({ type: 'directional', position: [12, 20, 8] }));
mountSceneInventory(game, inventory, {});
game.add(kccPlayer({ id: 'hero', position: [0, 1.5, 6] }));We built a fun Console OS web app to showcase the engine. Play it to see the physics, inputs, and graphics in action.
| Game | Description | Controls |
|---|---|---|
| 🪙 Quickstart Demo | The README hero character, coin sensor, audio chime, and particle burst VFX. | WASD / Arrows (Move), Space (Jump) |
| Aerodynamic physics, runway takeoff, landing gear, and ring course. | W/S (Pitch), A/D (Roll), Q/E (Yaw), Shift/Ctrl (Throttle), Z/X (Max/Cut), G (Gear), C (Camera), R (Reset) |
|
| 🔦 Echoes of Blackwood | Retro PSX 1st-person manor mystery: flashlight, clock puzzle, and escape. | WASD (Walk), Mouse (Look), F (Flashlight), E (Interact) |
Mobile support: Dual virtual sticks. Mid/high-end current phones target 45 FPS.
Renderoni uses tree-shakable subpath exports. Network exports have been removed for the beta.
| Subpath | Purpose |
|---|---|
renderoni |
Core createRenderoni entrypoint. |
renderoni/core |
Internal engine types (RenderoniEngine). |
renderoni/presets |
body, sensor, light, kccPlayer, proceduralModel. |
renderoni/animation |
Skeletal animation helpers. |
renderoni/audio |
Audio event records and hooks. |
renderoni/ui |
UI overlay components. |
renderoni/vfx |
Screen shake and VFX event hooks. |
renderoni/scene |
mountSceneInventory and scene parsing. |
renderoni/mcp |
Node.js MCP server entrypoint. |
renderoni/testing |
Framework-free assertion checks for headless tests. |
renderoni/testing/matchers |
Custom Vitest matchers (requires vitest peer dependency). |
renderoni/input |
Player input management. |
Renderoni targets consistent gameplay and run-to-run determinism across devices.
However, exact state hashes (bit-for-bit identical state) are currently only guaranteed on our pinned Node 22 Linux x64 CI matrix. Floating-point math variations in different browsers or architectures may cause minor hash divergences over long sessions.
To work on Renderoni itself:
npm install(Install dependencies)npm run dev(Start Vite dev server)npm run typecheck(Check types)npm test(Run unit and integration tests)npm run gate:beta(Run the beta validation suite)
- Support & Issues: GitHub Issues
- Security: Security Policy
- License: MIT License