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:
+4
-193
@@ -2,200 +2,11 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Runnable integration and focused addon recipes for the Yawn render core."
|
||||
/>
|
||||
<title>Yawn Examples</title>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
font-family: Inter, ui-sans-serif, system-ui, sans-serif;
|
||||
background: #0a0c0d;
|
||||
color: #f3f1e8;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; min-width: 320px; }
|
||||
body::before {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: -1;
|
||||
content: "";
|
||||
background:
|
||||
radial-gradient(circle at 75% 8%, #bb5b2b26, transparent 28rem),
|
||||
linear-gradient(#ffffff08 1px, transparent 1px),
|
||||
linear-gradient(90deg, #ffffff08 1px, transparent 1px),
|
||||
#0a0c0d;
|
||||
background-size: auto, 64px 64px, 64px 64px, auto;
|
||||
}
|
||||
a { color: inherit; }
|
||||
.shell { width: min(1180px, calc(100% - 40px)); margin: auto; }
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 82px;
|
||||
border-bottom: 1px solid #ffffff1a;
|
||||
}
|
||||
.wordmark { font-size: 18px; font-weight: 850; letter-spacing: .18em; }
|
||||
.wordmark span { color: #da7543; }
|
||||
header nav { display: flex; gap: 22px; color: #a9ada8; font-size: 13px; }
|
||||
header nav a { text-decoration: none; }
|
||||
header nav a:hover { color: #fff; }
|
||||
.hero { padding: 88px 0 58px; max-width: 820px; }
|
||||
.eyebrow,
|
||||
.recipe-number {
|
||||
color: #dc7543;
|
||||
font: 700 11px ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
letter-spacing: .14em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
h1 {
|
||||
margin: 16px 0 20px;
|
||||
max-width: 780px;
|
||||
font-size: clamp(48px, 8vw, 92px);
|
||||
font-weight: 760;
|
||||
letter-spacing: -.055em;
|
||||
line-height: .94;
|
||||
}
|
||||
.hero p { max-width: 660px; color: #b0b3ae; font-size: 18px; line-height: 1.65; }
|
||||
.primary {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.4fr) minmax(270px, .6fr);
|
||||
min-height: 340px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #ffffff20;
|
||||
border-radius: 18px;
|
||||
background: #111416e8;
|
||||
text-decoration: none;
|
||||
transition: border-color 160ms, transform 160ms;
|
||||
}
|
||||
.primary:hover { transform: translateY(-3px); border-color: #dc754388; }
|
||||
.primary-copy { padding: clamp(30px, 5vw, 64px); }
|
||||
.primary h2 { margin: 15px 0 12px; font-size: clamp(30px, 4vw, 52px); letter-spacing: -.035em; }
|
||||
.primary p { max-width: 580px; color: #aaafaa; font-size: 16px; line-height: 1.65; }
|
||||
.launch { display: inline-flex; align-items: center; gap: 10px; margin-top: 30px; font-weight: 720; }
|
||||
.launch span { color: #dc7543; font-size: 22px; transition: transform 160ms; }
|
||||
.primary:hover .launch span { transform: translateX(5px); }
|
||||
.primary-art {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
min-height: 260px;
|
||||
border-left: 1px solid #ffffff16;
|
||||
background: linear-gradient(145deg, #d57442, #6d2e1d);
|
||||
}
|
||||
.graph {
|
||||
position: relative;
|
||||
width: 190px;
|
||||
height: 165px;
|
||||
filter: drop-shadow(0 18px 25px #3d130b88);
|
||||
}
|
||||
.node { position: absolute; width: 78px; height: 48px; border: 1px solid #ffffff77; border-radius: 7px; background: #17191bd9; }
|
||||
.node::after { position: absolute; inset: 10px 13px; content: ""; border-top: 3px solid #fff; border-bottom: 3px solid #ffffff55; }
|
||||
.node:nth-child(1) { left: 0; top: 8px; }
|
||||
.node:nth-child(2) { right: 0; top: 58px; }
|
||||
.node:nth-child(3) { left: 20px; bottom: 0; }
|
||||
.edge { position: absolute; height: 1px; transform-origin: left; background: #fff9; }
|
||||
.edge-a { left: 70px; top: 48px; width: 77px; transform: rotate(19deg); }
|
||||
.edge-b { left: 92px; top: 135px; width: 70px; transform: rotate(-40deg); }
|
||||
.section-heading { display: flex; align-items: end; justify-content: space-between; gap: 20px; margin: 94px 0 26px; }
|
||||
.section-heading h2 { margin: 0; font-size: 34px; letter-spacing: -.03em; }
|
||||
.section-heading p { margin: 0; color: #929792; }
|
||||
.recipes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
|
||||
.recipe {
|
||||
min-height: 180px;
|
||||
padding: 25px;
|
||||
border: 1px solid #ffffff17;
|
||||
border-radius: 12px;
|
||||
background: #101315d9;
|
||||
text-decoration: none;
|
||||
transition: background 140ms, border-color 140ms;
|
||||
}
|
||||
.recipe:hover { border-color: #dc75436b; background: #17191b; }
|
||||
.recipe h3 { margin: 24px 0 8px; font-size: 17px; }
|
||||
.recipe p { margin: 0; color: #989d98; font-size: 13px; line-height: 1.55; }
|
||||
footer { display: flex; justify-content: space-between; gap: 20px; margin-top: 80px; padding: 34px 0 50px; border-top: 1px solid #ffffff1a; color: #858a85; font-size: 13px; }
|
||||
code { color: #d5d0c4; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
|
||||
@media (max-width: 850px) {
|
||||
.primary { grid-template-columns: 1fr; }
|
||||
.primary-art { min-height: 220px; border-top: 1px solid #ffffff16; border-left: 0; }
|
||||
.recipes { grid-template-columns: repeat(2, 1fr); }
|
||||
}
|
||||
@media (max-width: 560px) {
|
||||
.shell { width: min(100% - 24px, 1180px); }
|
||||
header nav a:first-child { display: none; }
|
||||
.hero { padding-top: 60px; }
|
||||
.recipes { grid-template-columns: 1fr; }
|
||||
.section-heading, footer { align-items: start; flex-direction: column; }
|
||||
}
|
||||
</style>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta http-equiv="refresh" content="0;url=/playground/" />
|
||||
<title>Yawn Playground</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="shell">
|
||||
<header>
|
||||
<div class="wordmark">YAWN<span>.</span></div>
|
||||
<nav aria-label="Examples navigation">
|
||||
<a href="#recipes">Recipes</a>
|
||||
<a href="https://github.com/heaust-ops/yawn">Repository ↗</a>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<section class="hero">
|
||||
<div class="eyebrow">Worker-native rendering toolkit</div>
|
||||
<h1>Build the graph.<br />Share the data.</h1>
|
||||
<p>
|
||||
Start with the complete interactive scene, then pull apart the focused
|
||||
recipes for graph ASTs, external pipelines, glTF workers, mesh handles,
|
||||
and direct shared-memory mutation.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<a class="primary" href="./render-graph-studio/">
|
||||
<div class="primary-copy">
|
||||
<div class="eyebrow">Interactive example · all packages</div>
|
||||
<h2>Render Graph Studio</h2>
|
||||
<p>
|
||||
Edit an FXNode graph, swap JSO loadouts, stream procedural glTF through
|
||||
shared memory, pick instances, and orbit the shared-SOA camera.
|
||||
</p>
|
||||
<div class="launch">Launch studio <span>→</span></div>
|
||||
</div>
|
||||
<div class="primary-art" aria-hidden="true">
|
||||
<div class="graph">
|
||||
<i class="node"></i><i class="node"></i><i class="node"></i>
|
||||
<i class="edge edge-a"></i><i class="edge edge-b"></i>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<section id="recipes" aria-labelledby="recipes-title">
|
||||
<div class="section-heading">
|
||||
<h2 id="recipes-title">Focused recipes</h2>
|
||||
<p>Small ES modules meant to copy, change, and combine.</p>
|
||||
</div>
|
||||
<div class="recipes">
|
||||
<a class="recipe" href="./cookbook/01-canonical-ast.js"><span class="recipe-number">01 · AST</span><h3>Canonical DAG</h3><p>Share one graph output through references and serialize it as an S-expression.</p></a>
|
||||
<a class="recipe" href="./cookbook/02-jso-graph.js"><span class="recipe-number">02 · JSO</span><h3>Plain object graph</h3><p>Describe a graph with ordinary JavaScript objects and compile to the canonical AST.</p></a>
|
||||
<a class="recipe" href="./cookbook/03-fluent-builder.js"><span class="recipe-number">03 · JSO</span><h3>Fluent builder</h3><p>Author the same public graph contract with a compact chainable API.</p></a>
|
||||
<a class="recipe" href="./cookbook/04-fxnode-export.js"><span class="recipe-number">04 · FXNode</span><h3>Snapshot export</h3><p>Turn an editor snapshot into the same AST consumed by every other frontend.</p></a>
|
||||
<a class="recipe" href="./cookbook/05-default-pipelines.js"><span class="recipe-number">05 · Pipelines</span><h3>Default loadout</h3><p>Attach the optional external pipeline addon without placing shaders in core.</p></a>
|
||||
<a class="recipe" href="./cookbook/06-custom-render-pipeline.js"><span class="recipe-number">06 · WGSL</span><h3>Custom render pipeline</h3><p>Provide scene WGSL, entry points, and state as graph-owned data.</p></a>
|
||||
<a class="recipe" href="./cookbook/07-compute-pipeline.js"><span class="recipe-number">07 · Compute</span><h3>Compute pipeline</h3><p>Declare a compute shader and dispatch dimensions inside the graph loadout.</p></a>
|
||||
<a class="recipe" href="./cookbook/08-compile-and-switch.js"><span class="recipe-number">08 · Lifecycle</span><h3>Compile and switch</h3><p>Prepare and transactionally activate compiled graph resources.</p></a>
|
||||
<a class="recipe" href="./cookbook/09-gltf-import-worker.js"><span class="recipe-number">09 · glTF</span><h3>Shared import worker</h3><p>Parse a URL in a worker and write generic render data directly into shared SOA memory.</p></a>
|
||||
<a class="recipe" href="./cookbook/10-mesh-instances.js"><span class="recipe-number">10 · Handles</span><h3>Mesh instances</h3><p>Use conventional generation-safe mesh and instance objects over the core protocol.</p></a>
|
||||
<a class="recipe" href="./cookbook/11-custom-soa-column.js"><span class="recipe-number">11 · SOA</span><h3>Custom column</h3><p>Request an aligned instance-sized array, then mutate it without messages.</p></a>
|
||||
<a class="recipe" href="./cookbook/12-direct-sab-animation.js"><span class="recipe-number">12 · SAB</span><h3>Direct animation</h3><p>Update guarded transforms at frame rate through shared memory.</p></a>
|
||||
<a class="recipe" href="./cookbook/13-bvh-picking.js"><span class="recipe-number">13 · Picking</span><h3>BVH picking</h3><p>Ray-pick shared scene data using the optional mesh-handles worker.</p></a>
|
||||
<a class="recipe" href="./cookbook/14-worker-to-worker.js"><span class="recipe-number">14 · Workers</span><h3>Worker to worker</h3><p>Run the public core API from any browser worker through a MessagePort.</p></a>
|
||||
<a class="recipe" href="./cookbook/15-complete-scene.js"><span class="recipe-number">15 · Complete</span><h3>Complete scene</h3><p>Combine graph, pipeline, glTF import, and mesh addons end to end.</p></a>
|
||||
<a class="recipe" href="./cookbook/16-camera-render-data.js"><span class="recipe-number">16 · Camera</span><h3>Camera render data</h3><p>Orbit, pan, and zoom by directly writing one SIMD-width SAB row.</p></a>
|
||||
<a class="recipe" href="./cookbook/17-conventional-handles.js"><span class="recipe-number">17 · Handles</span><h3>Camera and materials</h3><p>Use familiar camera and material properties while retaining direct SAB mutations.</p></a>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer><span>Yawn examples</span><code>npm run examples</code></footer>
|
||||
</div>
|
||||
<p><a href="/playground/">Open the Yawn Playground</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user