Ingest an unmodified three.js game
site/media/lessons/ingest-game.lesson.ts (4 steps) vgai can load a real, unmodified three.js game and edit it in-place. It doesn’t ask the game
to use a vgai API — it traps the game’s render call, reads the Scene the game hands its
WebGLRenderer, and exposes that live Object3D tree to the editor through a neutral
AuthoringAdapter. Edits are stored separately as an overlay, so the game’s source stays
untouched.
-
Open the editor. A normal editor session. Use the
?ingest=interactive-cubeslink above to launch it in your browser (the same flow runs headlessly via the ingest dev hook in CI).
An ordinary editor session. -
Ingest an unmodified three.js game. The link loads the upstream Interactive Cubes example — no vgai changes to its code.
Loading an unmodified three.js game. -
The foreign game runs live — via the render-accessor trap.
adapter/ingest/scene-capture.tswraps the hostWebGLRenderer.renderso the first(scene, camera)the game renders is captured. The game runs exactly as written; vgai just observes its scene.
An unmodified three.js game, running inside the editor. -
The editor panels drive the ingested tree. The captured
Object3Dtree is presented through the same neutralAuthoringAdapterthe 3D and 2D surfaces use, so the hierarchy/inspector work on a foreign game with no special-casing.
One authoring contract drives a foreign game's tree.
Recap
New functionality
- Ingested an unmodified three.js game into the editor
- Saw its live Object3D tree in the editor panels
New concepts & skills
- The render-accessor trap captures the Scene the game renders — no game-side API
- A neutral AuthoringAdapter drives the foreign tree (same contract as 3D/2D)
- iframe tiers degrade gracefully; edits persist as a separate overlay (.vgai/overlays)
Next lesson → Loading existing games (manual)
Ingest your own folder
Section titled “Ingest your own folder”The mechanism is not vendored-games-only: the same { ingest } manifest works for a
three.js game folder that has never seen this repo. Put a vgai.game.json next to your
game:
{ "manifestVersion": 2, "name": "My Existing Game", "version": "0.1.0", "engine": { "version": "0.1.0" }, "roots": [ { "id": "main", "adapter": { "surface": "threejs", "ingest": { "strategy": "iframe-reachable", "entryHtml": "index.html" } } } ]}then open the folder in the editor (npx @vgai/cli@latest edit <folder>, or the
editor’s open-project flow). The resolver mounts it through the same ingest machinery you
just used; edits land in .vgai/overlays/ in your folder, and your game source is never
touched. The strategy field is the capability declaration — iframe-reachable needs your
three to be reachable in-realm (import-map builds qualify; an opaque prebuilt bundle
falls back to embed-only). The JSON-Schema for the manifest (autocomplete + field docs)
ships in the engine package.
Scope honesty: this bring-your-own path works for three.js, PixiJS, and React games —
declare an { ingest, surface } adapter root in your own vgai.game.json and
open the folder (React’s manifest/external-folder route is the newest
of the three). The vendored games shown in this section exist to prove the mechanism in CI,
not because any of the three kinds is vendored-only — see docs/BRINGING-AN-EXISTING-GAME.md
in the checkout for the full per-kind capability map and the adapt-vs-port decision guide.