Genshin Engine

SkillDev tools

Apply when writing or reviewing code in packages/genshin-engine or packages/genshin-world, the app's Genshin components under components/Genshin, or any TSL material, post pass, generator or kit for it. Esposter's Genshin engine, a published package of plain TypeScript and TSL modules, and the world package that builds the game's regions on it in TresJS components, built to run cheaply in the reader's own browser.

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the Genshin Engine skill

What this skill tells your AI

The instructions your AI receives, as published by esposter/esposter in .agents/skills/genshin-engine/SKILL.md and read by ahel’s review.

The design, from each module's job to the order a frame runs in, is apps/web/content/docs/proposals/genshin/engine-architecture.md; this skill is the rules a change to the engine or its world follows.

Settled — do not re-propose

  • A rigid-body physics engine (Rapier, cannon) for collision. Movement is kinematic, so collision is a query service the controller asks; a solver fights the feel (engine-architecture.md, "Collision is a query service").
  • An ignorePatterns entry for the engine's TSL. The engine lints in about a second, so the fluid simulator's file stays the only exclusion (.agents/skills/oxlint/references/ignore-patterns.md).
  • Shipping assets taken from the game — models, textures, sounds or art, extracted or converted. Every mesh, texture and shader is generated by our own code, re-derived from the game's exports as closely as they allow (apps/web/content/docs/proposals/genshin/scene-derivation.md).
  • The word "teyvat" in any name — package, folder, route, page or prose. The world is implicit in "Genshin".
  • A second renderer path for WebGL. WebGPURenderer falls back to WebGL 2 on its own.

Rules

  • The engine has no Vue, no store and no DOM beyond a canvas, and no place. genshin-engine is the renderer and the generators, and knows no region by name. genshin-world is the game's world on it: the catalogue, the regions' data, and the TresJS layer — components and composables such as usePostPipeline — that creates the engine's modules. The world's screen (WorldScreen) owns its canvas; the app keeps only the opening (components/Genshin/Index.vue), its stores, and the bundler's seams, which the world takes as props: the terrain worker's factory, the URL region data is fetched from, and the tuning panel's visibility.
  • A generator is pure and seeded, and returns typed arrays: computeX(options) does the work with no three.js object per vertex, and createXGeometry only wraps its arrays in a BufferGeometry. The compute* function is what is tested and benched.
  • Nothing allocates per vertex or per frame. Write into the output buffer by index, and pass a writer (writeColor(colors, offset, …)) rather than returning a tuple.
  • Every generator and per-frame selection is benched at two scales or more, under the bench skill, and its cost must follow what is drawn, never the size of the world.
  • Light is shared uniforms, and the sky writes them. Every material reads one LightUniforms from createLightUniforms, so the hour moves by writing a few values, not by walking materials. A region's light is its SkyKeyframes, written each frame by applySkyState, never a colour set on a light by hand.
  • Environment surfaces use createToonMaterial over the world's one ramp texture; shade is the ambient (hemisphere) light's colour, never a darker multiply, and the rim is the material's emissive node on ToonNodeMaterial. Stone the game lights in its deferred pass (the login's towers, walkway and door) is createStoneMaterial instead, lit by StoneLightingModel from one shared StoneLightUniforms an hour writes with applyStoneLight.
  • The frame is drawn by the engine's post pipeline. usePostPipeline replaces TresJS's render with createPostPipeline: outlines, screen-space occlusion where a scene passes its radius, god rays, height fog and bloom in that order, then TRAA ahead of the tone mapping and the grade, or SMAA after them (apps/web/content/docs/genshin/rendering-style.md). A scene whose colours are measured off references through the tone mapping alone, as the login's are, passes no grade table, no god rays' light and isBloomed: false, so each measured colour inverts exactly. A quality tier removes cost, never the ramp, the rim or the outline (QualityTierSettingsMap).
  • Ground is not outlined. A terrain material passes isOutlined: false, since the outline pass picks materials by three's toon flag alone and a ridge would otherwise draw ink against the sky.
  • The sun casts through cascades; the god rays read their own sun. createSunLight attaches CSMShadowNode, and GodraysNode marches through createGodraysLight's one map, drawn only when shadow.needsUpdate is set: applySkyState sets it as the light turns, and whatever replaces the ground under the view sets it too.
  • A look value is tuned in development's panel, then copied into the region's constants. useGenshinTuning writes uniforms and regenerates textures live and saves nothing.
  • The ground streams; nothing places a heightfield by hand. A region's heights and colours reach the ground only through the terrain worker (packages/genshin-world/src/workers/terrainTile.worker.ts), and everything placed in the world sits inside the floating origin's world group, so a shift moves it with the ground (apps/web/content/docs/genshin/terrain.md).
  • There is one wind. Anything that moves in the wind samples createWindNode over the world's WindUniforms, never a sway of its own, so a gust moves the grass, the crowns and the clouds together (apps/web/content/docs/genshin/vegetation.md).
  • Region data is the world package's: heights, colours and look for a place live in packages/genshin-world/src/services/<place>/, its landmarks in src/data/regions/<region>.json (served by the app's server at GENSHIN_REGION_DATA_BASE_URL), and the engine only exposes what consumes them.
  • The world package is published and builds through getTsdownConfigurationVue(templateCompilerOptions), so its templates' Tres* tags compile as the renderer's elements. It reaches Vue's own APIs through auto-imports and names TresJS's and VueUse's imports. Its terrain worker is its own entry (genshin-world/terrainTileWorker), which the app bundles with ?worker.
  • One export per file, #src/* imports, explicit return types — the package is published with isolated declarations, so every exported function states its type.

Signals

GitHub stars
23
Forks
3
Last commit
Oct 2026
Advanced
Item type
skill
Key
genshin-engine
Source
github.com/esposter/esposter