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:
@@ -0,0 +1,134 @@
|
||||
import { YawnCore } from "@yawn/core";
|
||||
import { GltfImporter } from "@yawn/gltf-import";
|
||||
import {
|
||||
CameraHandle,
|
||||
MaterialHandles,
|
||||
MeshHandles,
|
||||
} from "@yawn/mesh-handles";
|
||||
import { loadGraph, graphFromObject, RenderGraph, ref } from "@yawn/render-graph-js";
|
||||
import {
|
||||
createGraphAst,
|
||||
reference,
|
||||
serializeGraphAst,
|
||||
} from "@yawn/render-graph-ast";
|
||||
import { defaultPipelines } from "@yawn/default-pipelines";
|
||||
import { loadDemoLoadout } from "../render-graph-studio/demo-loadouts.js";
|
||||
import { culling } from "../render-graph-studio/render-graph/presets.js";
|
||||
import { installCameraRenderDataControls } from "../shared/camera-controls.js";
|
||||
import { createWorkerTransport } from "../shared/create-worker-transport.js";
|
||||
|
||||
const waitForFrame = (core, predicate, timeout = 30_000) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const current = core.telemetry;
|
||||
if (current && predicate(current)) {
|
||||
resolve(current);
|
||||
return;
|
||||
}
|
||||
const timer = setTimeout(() => {
|
||||
core.removeEventListener("renderer-frame", frame);
|
||||
reject(new Error("Renderer confirmation timed out"));
|
||||
}, timeout);
|
||||
const frame = (event) => {
|
||||
if (!predicate(event.detail)) return;
|
||||
clearTimeout(timer);
|
||||
core.removeEventListener("renderer-frame", frame);
|
||||
resolve(event.detail);
|
||||
};
|
||||
core.addEventListener("renderer-frame", frame);
|
||||
});
|
||||
|
||||
export function rotationY(angle) {
|
||||
const cosine = Math.cos(angle);
|
||||
const sine = Math.sin(angle);
|
||||
return [
|
||||
cosine, 0, -sine, 0,
|
||||
0, 1, 0, 0,
|
||||
sine, 0, cosine, 0,
|
||||
0, 0, 0, 1,
|
||||
];
|
||||
}
|
||||
|
||||
export function createPlaygroundRuntime(canvas, report) {
|
||||
let activeScene;
|
||||
const status = (message) => {
|
||||
report(String(message));
|
||||
};
|
||||
|
||||
async function createScene({ loadout = "cubes", graph = culling } = {}) {
|
||||
activeScene?.dispose();
|
||||
const core = new YawnCore(createWorkerTransport(canvas));
|
||||
const handles = new MeshHandles(core);
|
||||
const importer = new GltfImporter(core);
|
||||
let stopControls = () => {};
|
||||
try {
|
||||
status("Starting render worker…");
|
||||
await core.ready;
|
||||
const compiled = await loadGraph(core, graph);
|
||||
const targetRevision = (core.telemetry?.revision ?? 0) + 1;
|
||||
const glb = await loadDemoLoadout(loadout);
|
||||
const url = URL.createObjectURL(
|
||||
new Blob([glb], { type: "model/gltf-binary" }),
|
||||
);
|
||||
let imported;
|
||||
try {
|
||||
imported = await importer.load(url);
|
||||
} finally {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
const meshes = handles.fromImportedScene(imported);
|
||||
const materials = new MaterialHandles(core).fromImportedScene(imported);
|
||||
const camera = new CameraHandle(core);
|
||||
stopControls = installCameraRenderDataControls(core, canvas);
|
||||
await core.switchCompiledGraph(compiled.compiledId);
|
||||
await waitForFrame(
|
||||
core,
|
||||
(frame) =>
|
||||
frame.revision === targetRevision &&
|
||||
frame.activeCompiledGraph === graph.id &&
|
||||
frame.draws > 0 &&
|
||||
frame.gpuError === false,
|
||||
);
|
||||
activeScene = {
|
||||
core,
|
||||
handles,
|
||||
meshes,
|
||||
materials,
|
||||
camera,
|
||||
compiled: { ...compiled, graphId: graph.id },
|
||||
dispose() {
|
||||
stopControls();
|
||||
handles.dispose();
|
||||
core.dispose();
|
||||
activeScene = undefined;
|
||||
},
|
||||
};
|
||||
return activeScene;
|
||||
} catch (error) {
|
||||
stopControls();
|
||||
handles.dispose();
|
||||
core.dispose();
|
||||
throw error;
|
||||
} finally {
|
||||
importer.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return Object.freeze({
|
||||
createScene,
|
||||
status,
|
||||
rotationY,
|
||||
graphs: Object.freeze({ culling }),
|
||||
packages: Object.freeze({
|
||||
createGraphAst,
|
||||
defaultPipelines,
|
||||
graphFromObject,
|
||||
reference,
|
||||
ref,
|
||||
RenderGraph,
|
||||
serializeGraphAst,
|
||||
}),
|
||||
dispose() {
|
||||
activeScene?.dispose();
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user