Amp-Thread-ID: https://ampcode.com/threads/T-01a02485-5574-707c-bff4-5668d83bee8a Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
289 lines
10 KiB
HTML
289 lines
10 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<meta name="theme-color" content="#f7fbff" />
|
||
<meta
|
||
name="description"
|
||
content="Write, run, profile, and share Yawn WebGPU scenes."
|
||
/>
|
||
<title>Yawn Playground</title>
|
||
<script src="/assets/theme.js"></script>
|
||
<link rel="stylesheet" href="/assets/playground.css" />
|
||
<link rel="stylesheet" href="/assets/theme.css" />
|
||
<script type="importmap">
|
||
{
|
||
"imports": {
|
||
"@yawn/core": "/pkg/core.js",
|
||
"@yawn/handles": "/pkg/handles.js"
|
||
}
|
||
}
|
||
</script>
|
||
<script src="/assets/monaco/vs/loader.js"></script>
|
||
<script type="module" src="/assets/playground.js"></script>
|
||
</head>
|
||
<body>
|
||
<main class="playground-app">
|
||
<header class="playground-header">
|
||
<a class="playground-brand" href="/" aria-label="Yawn home">
|
||
<span class="brand-mark" aria-hidden="true"
|
||
><i></i><i></i><i></i></span
|
||
><strong>Yawn</strong>
|
||
</a>
|
||
<div class="header-divider"></div>
|
||
<div class="project-name">
|
||
<input
|
||
id="project-title"
|
||
maxlength="80"
|
||
value="Three-light icosphere"
|
||
aria-label="Playground title"
|
||
/>
|
||
<span id="dirty-indicator" title="Unsaved changes"></span>
|
||
<span id="revision-label">Draft</span>
|
||
</div>
|
||
<nav class="playground-nav" aria-label="Playground links">
|
||
<a href="/docs">Docs</a>
|
||
<a href="https://git.heaust.org/heaust/yawn">Source</a>
|
||
</nav>
|
||
<select class="theme-select" data-theme-select aria-label="Color theme">
|
||
<option value="auto">Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
<button id="share-button" class="tool-button" type="button" hidden>
|
||
<span aria-hidden="true">↗</span> Share
|
||
</button>
|
||
<button id="save-button" class="tool-button" type="button">
|
||
<span aria-hidden="true">◇</span> Save
|
||
</button>
|
||
<button id="run-button" class="run-button" type="button">
|
||
<span aria-hidden="true">▶</span> Run <kbd>Ctrl ↵</kbd>
|
||
</button>
|
||
</header>
|
||
|
||
<div class="playground-tools">
|
||
<div class="tool-group">
|
||
<button id="snippets-button" type="button">
|
||
<span class="braces">{ }</span> Snippets
|
||
</button>
|
||
<button id="reset-button" type="button">
|
||
<span aria-hidden="true">↶</span> Reset
|
||
</button>
|
||
<button id="format-button" type="button">
|
||
<span aria-hidden="true">≡</span> Format
|
||
</button>
|
||
</div>
|
||
<div class="tool-context">
|
||
<span class="language-dot"></span>
|
||
<span>TypeScript</span>
|
||
<span class="context-divider"></span>
|
||
<span id="type-status">Starting language service…</span>
|
||
</div>
|
||
<div class="tool-group tool-group-right">
|
||
<button id="inspector-button" type="button" aria-pressed="true">
|
||
<span aria-hidden="true">▤</span> Inspector
|
||
</button>
|
||
<button
|
||
id="fullscreen-button"
|
||
type="button"
|
||
aria-label="Toggle fullscreen"
|
||
>
|
||
<span aria-hidden="true">⛶</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="workbench" id="workbench">
|
||
<section class="editor-pane" aria-label="TypeScript editor">
|
||
<div class="pane-tabs">
|
||
<button class="pane-tab active" type="button">
|
||
<span class="ts-icon">TS</span> scene.ts <i id="tab-dirty"></i>
|
||
</button>
|
||
</div>
|
||
<div id="editor" class="editor">
|
||
<div class="editor-loading">Loading TypeScript editor…</div>
|
||
</div>
|
||
<footer class="editor-status">
|
||
<span id="cursor-status">Ln 1, Col 1</span>
|
||
<span>Spaces: 2</span>
|
||
<span>UTF-8</span>
|
||
<span class="status-spacer"></span>
|
||
<span id="editor-diagnostics"><i></i> No problems</span>
|
||
</footer>
|
||
</section>
|
||
|
||
<div
|
||
class="resize-handle"
|
||
id="resize-handle"
|
||
role="separator"
|
||
aria-orientation="vertical"
|
||
aria-label="Resize editor and preview"
|
||
></div>
|
||
|
||
<section class="stage-pane" aria-label="Yawn output">
|
||
<div class="stage-toolbar">
|
||
<div class="stage-tabs">
|
||
<button type="button" class="active">Preview</button>
|
||
</div>
|
||
<div class="stage-meta">
|
||
<span id="run-status"><i></i> Ready</span>
|
||
<span class="stage-divider"></span>
|
||
<span id="fps-status">0 FPS</span>
|
||
<span class="stage-divider"></span>
|
||
<span id="resolution-status">—</span>
|
||
</div>
|
||
</div>
|
||
<div class="preview" id="preview">
|
||
<canvas id="canvas" aria-label="Yawn WebGPU preview"></canvas>
|
||
<div class="preview-message" id="preview-message">
|
||
<span class="preview-message-icon">Y</span>
|
||
<strong>Preparing your scene</strong>
|
||
<small>The first run compiles the render graph.</small>
|
||
</div>
|
||
</div>
|
||
<div class="inspector" id="inspector">
|
||
<div class="inspector-tabs" role="tablist">
|
||
<button
|
||
type="button"
|
||
class="active"
|
||
role="tab"
|
||
aria-selected="true"
|
||
data-panel="console"
|
||
>
|
||
Console <span id="console-count">0</span>
|
||
</button>
|
||
<button
|
||
type="button"
|
||
role="tab"
|
||
aria-selected="false"
|
||
data-panel="profile"
|
||
>
|
||
GPU profiler
|
||
</button>
|
||
<button id="clear-console" class="clear-console" type="button">
|
||
Clear
|
||
</button>
|
||
</div>
|
||
<div
|
||
class="console-panel inspector-panel active"
|
||
id="console-panel"
|
||
role="tabpanel"
|
||
>
|
||
<div class="console-empty" id="console-empty">
|
||
<span>›_</span> Output from <code>log()</code> appears here.
|
||
</div>
|
||
<ol id="console-lines"></ol>
|
||
</div>
|
||
<div
|
||
class="profile-panel inspector-panel"
|
||
id="profile-panel"
|
||
role="tabpanel"
|
||
>
|
||
<div class="profile-empty" id="profile-empty">
|
||
<span class="pulse-icon">⌁</span>
|
||
<div>
|
||
<strong>Waiting for GPU timestamps</strong
|
||
><small>Run the scene to inspect its physical passes.</small>
|
||
</div>
|
||
</div>
|
||
<div class="profile-results" id="profile-results" hidden>
|
||
<div class="profile-summary">
|
||
<div>
|
||
<small>Total GPU time</small
|
||
><strong id="profile-total">—</strong>
|
||
</div>
|
||
<div>
|
||
<small>Readback latency</small
|
||
><strong id="profile-latency">—</strong>
|
||
</div>
|
||
<div>
|
||
<small>Adapter</small
|
||
><strong id="profile-adapter">—</strong>
|
||
</div>
|
||
</div>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Physical pass</th>
|
||
<th>GPU time</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="profile-passes"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</main>
|
||
|
||
<dialog id="snippets-dialog" class="snippets-dialog">
|
||
<div class="dialog-heading">
|
||
<div>
|
||
<span>Code library</span>
|
||
<h2>Snippets</h2>
|
||
<p>Insert a focused building block at your cursor.</p>
|
||
</div>
|
||
<button type="button" data-close-dialog aria-label="Close snippets">
|
||
×
|
||
</button>
|
||
</div>
|
||
<div class="snippet-search">
|
||
<span>⌕</span
|
||
><input
|
||
type="search"
|
||
placeholder="Find a snippet"
|
||
aria-label="Find a snippet"
|
||
/>
|
||
</div>
|
||
<div class="snippet-grid">
|
||
<button type="button" data-snippet="camera">
|
||
<span class="snippet-icon">◎</span>
|
||
<div>
|
||
<strong>Orbit camera</strong
|
||
><small>Pointer orbit and wheel zoom</small
|
||
><code>ArcRotateCamera</code>
|
||
</div>
|
||
<b>+</b>
|
||
</button>
|
||
<button type="button" data-snippet="light">
|
||
<span class="snippet-icon">☀</span>
|
||
<div>
|
||
<strong>Point light</strong><small>Warm, local illumination</small
|
||
><code>PointLight</code>
|
||
</div>
|
||
<b>+</b>
|
||
</button>
|
||
<button type="button" data-snippet="instances">
|
||
<span class="snippet-icon">◇</span>
|
||
<div>
|
||
<strong>Mesh instances</strong><small>Clone shared geometry</small
|
||
><code>mesh.clone()</code>
|
||
</div>
|
||
<b>+</b>
|
||
</button>
|
||
<button type="button" data-snippet="rows">
|
||
<span class="snippet-icon">≋</span>
|
||
<div>
|
||
<strong>Shared rows</strong
|
||
><small>Add application-owned hot data</small
|
||
><code>scene.ensureRows()</code>
|
||
</div>
|
||
<b>+</b>
|
||
</button>
|
||
<button type="button" data-snippet="post">
|
||
<span class="snippet-icon">✦</span>
|
||
<div>
|
||
<strong>Post processing</strong><small>Color grading and FXAA</small
|
||
><code>batchGraphUpdates()</code>
|
||
</div>
|
||
<b>+</b>
|
||
</button>
|
||
</div>
|
||
</dialog>
|
||
|
||
<div class="toast" id="toast" role="status" aria-live="polite"></div>
|
||
</body>
|
||
</html>
|