Amp-Thread-ID: https://ampcode.com/threads/T-01a01380-b478-77d0-84a0-102880a5c5ae Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
105 lines
4.0 KiB
JavaScript
105 lines
4.0 KiB
JavaScript
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"];
|
|
}
|