Add tutorial docs and interactive playgrounds

Amp-Thread-ID: https://ampcode.com/threads/T-01a01380-b478-77d0-84a0-102880a5c5ae
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-08-19 14:20:59 +00:00
co-authored by heaust
parent 6bbf8039e4
commit d34722d66d
57 changed files with 5063 additions and 767 deletions
+104
View File
@@ -0,0 +1,104 @@
export const PLAYGROUND_RECIPES = Object.freeze({
"first-scene": Object.freeze({
title: "Your first scene",
package: "All packages",
description: "Boot core, load procedural glTF through the import worker, and activate a graph.",
docs: "/docs/guide/first-scene",
source: `const scene = await yawn.createScene({ loadout: "cubes" });
yawn.status(
\`Ready · \${scene.meshes.length} meshes · \${scene.core.telemetry.draws} draws\`,
);`,
}),
"jso-graph": Object.freeze({
title: "Load a JSO render graph",
package: "@yawn/render-graph-js",
description: "Compile a plain-object graph through the canonical AST boundary.",
docs: "/docs/packages/render-graph#plain-object-authoring",
source: `const scene = await yawn.createScene({
loadout: "spheres",
graph: yawn.graphs.culling,
});
yawn.status(
\`Graph \${scene.compiled.graphId} · \${scene.core.telemetry.draws} draws\`,
);`,
}),
"gltf-worker": Object.freeze({
title: "Import glTF in a worker",
package: "@yawn/gltf-import",
description: "Stage a generated GLB in shared memory and commit only metadata.",
docs: "/docs/packages/gltf-import",
source: `const scene = await yawn.createScene({ loadout: "spheres" });
yawn.status(
\`Imported \${scene.meshes.length} mesh handles through shared memory\`,
);`,
}),
"shared-animation": Object.freeze({
title: "Animate through the SAB",
package: "@yawn/core",
description: "Write a generation-guarded instance transform every frame without messages.",
docs: "/docs/packages/core#fast-path-shared-writes",
source: `const scene = await yawn.createScene({ loadout: "cubes" });
const instance = scene.meshes[0].defaultInstance;
const start = performance.now();
function animate(now) {
const angle = (now - start) * 0.001;
instance.setTransform(yawn.rotationY(angle));
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
yawn.status("Animating instance.transform directly in shared memory");`,
}),
"custom-soa": Object.freeze({
title: "Allocate custom render data",
package: "@yawn/core",
description: "Add one aligned velocity row for every instance slot.",
docs: "/docs/packages/core#request-an-soa-column",
source: `const scene = await yawn.createScene({ loadout: "cubes" });
const velocity = await scene.core.allocateArray({
name: "instance.velocity",
domain: "instance",
scalar: "f32",
lanes: 4,
});
for (const mesh of scene.meshes) {
velocity.write(mesh.defaultInstance.handle[0], [0, 0.25, 0, 0]);
}
yawn.status(\`Allocated \${velocity.length} SIMD-aligned velocity rows\`);`,
}),
"conventional-handles": Object.freeze({
title: "Camera and material handles",
package: "@yawn/mesh-handles",
description: "Use familiar properties while mutations remain direct shared-memory writes.",
docs: "/docs/packages/mesh-handles#camera-and-material-handles",
source: `const scene = await yawn.createScene({ loadout: "materials" });
scene.camera.lookAt([11, 9, 13], [0, 0, 0]);
const material = scene.materials[1];
material.baseColor = [0.1, 0.55, 1, 1];
material.metallic = 0.15;
material.roughness = 0.28;
yawn.status("Camera and material properties committed through SAB rows");`,
}),
picking: Object.freeze({
title: "Pick shared scene data",
package: "@yawn/mesh-handles",
description: "Build the optional worker-side BVH and query the closest instance.",
docs: "/docs/packages/mesh-handles#worker-side-picking",
source: `const scene = await yawn.createScene({ loadout: "cubes" });
const state = scene.camera.state;
const origin = state.slice(0, 3);
const direction = state.slice(4, 7).map((value, axis) => value - origin[axis]);
const result = await scene.handles.pickRay(origin, direction, { maxHits: 1 });
yawn.status(
result.hits.length
? \`Picked instance \${result.hits[0].instance.handle.join(":")}\`
: "No instance intersected the center ray",
);`,
}),
});
export function playgroundRecipe(id) {
return PLAYGROUND_RECIPES[id] ?? PLAYGROUND_RECIPES["first-scene"];
}