TripoSplat-WebGPU / e2e-web.html
Yosun's picture
Publish prebuilt WebGPU demo
c18dbb7 verified
Raw
History Blame Contribute Delete
12.3 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="dark" />
<meta name="theme-color" content="#070a12" />
<meta name="description" content="Generate a Gaussian splat from an image using browser-local WebGPU." />
<title>TripoSplat WebGPU · Image to 3D Offline Local</title>
<script type="module" crossorigin src="/assets/e2eWeb-Dy472OlL.js"></script>
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
<link rel="modulepreload" crossorigin href="/assets/index-CMkL1IIy.js">
<link rel="modulepreload" crossorigin href="/assets/client-CiuGHKKk.js">
<link rel="modulepreload" crossorigin href="/assets/index-BtoLWqnT.js">
<link rel="modulepreload" crossorigin href="/assets/preload-helper-BXl3LOEh.js">
<link rel="modulepreload" crossorigin href="/assets/SplatPreview-D3bCUQ8P.js">
<link rel="stylesheet" crossorigin href="/assets/e2eWeb-x5D6tN2d.css">
</head>
<body>
<a class="skip-link" href="#main-content">Skip to generator</a>
<div class="ambient ambient-one" aria-hidden="true"></div>
<div class="ambient ambient-two" aria-hidden="true"></div>
<nav class="topbar" aria-label="Primary navigation">
<a class="brand" href="/e2e-web.html" aria-label="TripoSplat WebGPU image to 3D">
<span class="brand-mark" aria-hidden="true"><span></span></span><span>TRIPOSPLAT <b>WEBGPU</b></span>
</a>
<span class="capability" id="platform-badge"><i></i><span>Checking platform</span></span>
</nav>
<main id="main-content" class="app-shell web-app">
<header class="web-hero">
<div class="eyebrow"><span>Image to 3D Model. </span></div>
<h1><em>Offline. Local. Portable.</em></h1>
<p>Your browser uses WebGPU to run the full TripoSplat model locally.<br />
The ≈6.5 GB model package downloads once, verifies, and stays in offline browser storage.<br />
After that, it is ready to run again without another model download.</p>
<div class="hero-actions"><a class="github-link" href="#source-heading">Try it out <span aria-hidden="true"></span></a><a class="hero-text-link" href="#browser-experiment">Why this matters <span aria-hidden="true"></span></a></div>
</header>
<section class="compatibility-panel" aria-labelledby="compatibility-heading">
<div><span class="section-index">SYSTEM CHECK</span><h2 id="compatibility-heading">Preparing your browser</h2></div>
<ul id="compatibility-list" aria-live="polite"><li>Checking WebGPU and storage…</li></ul>
</section>
<div class="web-workspace">
<section class="web-controls panel" aria-labelledby="source-heading">
<div class="panel-heading"><div><span class="section-index">STEP 1 / IMAGE</span><h2 id="source-heading">Choose a starting image</h2></div><span class="local-badge">ON DEVICE</span></div>
<p class="panel-copy">Use an alpha-bearing PNG or WebP for best results. Transparent background tells the model what to turn into a scene.</p>
<input id="image-file" type="file" accept="image/png,image/webp,image/jpeg,image/avif" hidden />
<button id="choose-file" class="file-picker" type="button"><span>Choose image from your computer</span><b>Browse</b></button>
<label class="url-label" for="image-url"><span>Or start from an image URL</span><small id="image-url-help">The image host must allow browser CORS access.</small></label>
<div class="url-row"><input id="image-url" type="url" inputmode="url" placeholder="https://example.com/object.png" autocomplete="url" aria-describedby="image-url-help image-url-error" /><button id="load-image-url" type="button">Use URL</button></div>
<div id="image-url-error" class="image-url-error" role="alert" hidden></div>
<figure id="image-preview" class="image-preview" hidden>
<img id="image-preview-image" alt="Selected source image preview" />
<figcaption>Loaded source image</figcaption>
</figure>
<div id="image-summary" class="image-summary" data-state="empty" aria-live="polite">No image selected yet.</div>
<button id="drop-zone" class="drop-zone" type="button">Or drag an image here</button>
<a class="continue-to-engine" href="#model-heading">Continue to browser engine <span aria-hidden="true"></span></a>
</section>
<section class="preview-panel-web panel" aria-labelledby="scene-heading">
<div class="panel-heading"><div><span class="section-index">STEP 3 / RESULT</span><h2 id="scene-heading">Your spatial scene</h2></div><span id="viewer-state" class="viewer-state">Waiting</span></div>
<div id="web-preview-root"></div>
<p id="preview-run-state" class="preview-run-state" data-state="waiting" role="status" aria-live="polite">A completed scene will appear here without leaving this page.</p>
<div class="download-row"><button id="download-ply" type="button" disabled>Download PLY</button><button id="download-splat" type="button" disabled>Download .splat</button></div>
</section>
</div>
<section class="model-panel panel" aria-labelledby="model-heading">
<div class="panel-heading"><div><span class="section-index">STEP 2 / BROWSER ENGINE</span><h2 id="model-heading">Preparing the model</h2></div><span id="cache-mode" class="local-badge">CACHE CHECK</span></div>
<p class="panel-copy">Your first run downloads roughly 6.47 GB from the official browser-runtime package, verifies every file, and stores it locally when your browser permits it. You only need to choose an image.</p>
<div class="model-layout"><div id="model-status" class="model-status" aria-live="polite">Checking model and browser storage…</div></div>
<details class="model-advanced"><summary>Use a different model server</summary><label for="model-base"><span>Model CDN directory</span><small>Must contain manifest.json and allow CORS requests from this site.</small><input id="model-base" type="url" inputmode="url" autocomplete="url" spellcheck="false" /></label></details>
<button id="generate" class="primary-action" type="button" disabled><span>Choose an image to begin</span><b aria-hidden="true"></b></button>
<div class="run-feedback"><small id="run-stage">STATUS</small><p id="run-status" aria-describedby="run-stage">Checking browser compatibility…</p><span id="run-announcement" class="visually-hidden" role="status" aria-live="polite" aria-atomic="true"></span><div class="progress-track" role="progressbar" aria-label="Generation progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><span id="progress-fill"></span></div></div>
<section class="generation-flow" aria-labelledby="generation-flow-heading">
<div class="flow-heading"><div><span class="section-index">ENGINEERING PIPELINE</span><h3 id="generation-flow-heading">What this browser is doing</h3></div><div class="progress-detail-switch" role="group" aria-label="Progress detail level"><button type="button" data-progress-detail="guided" aria-pressed="false">Guided</button><button type="button" data-progress-detail="technical" aria-pressed="true">Technical</button></div></div>
<p id="progress-detail-description" class="progress-detail-description">Technical mode shows exact graph stages, sampler steps, CFG invocations, and decode boundaries as they happen.</p>
<ol id="generation-flow" class="flow-steps">
<li data-flow-stage="source" data-state="active" aria-current="step"><span class="flow-marker">01</span><div><strong>Source image</strong><span>Inspect alpha and prepare local pixels.</span></div><small>READY</small></li>
<li data-flow-stage="model" data-state="waiting"><span class="flow-marker">02</span><div><strong>Model package</strong><span>Verify manifest, integrity, and browser cache.</span></div><small>WAITING</small></li>
<li data-flow-stage="conditioning" data-state="waiting"><span class="flow-marker">03</span><div><strong>Conditioning</strong><span>Preprocess → DINOv3 → Flux VAE.</span></div><small>WAITING</small></li>
<li data-flow-stage="sampling" data-state="waiting"><span class="flow-marker">04</span><div><strong>Flow sampler</strong><span>20 official steps · 40 CFG DiT calls.</span></div><small>WAITING</small></li>
<li data-flow-stage="decode" data-state="waiting"><span class="flow-marker">05</span><div><strong>Spatial decode</strong><span>Octree occupancy → Gaussian decoder.</span></div><small>WAITING</small></li>
<li data-flow-stage="preview" data-state="waiting"><span class="flow-marker">06</span><div><strong>Scene handoff</strong><span>Encode PLY / .splat and swap the viewer.</span></div><small>WAITING</small></li>
</ol>
</section>
<section id="benchmark-report" class="benchmark-report" aria-labelledby="benchmark-heading" hidden>
<div class="flow-heading"><div><span class="section-index">RUN REPORT</span><h3 id="benchmark-heading">Copyable benchmark summary</h3></div><button id="copy-benchmark" type="button" disabled>Copy report</button></div>
<p id="benchmark-summary" class="benchmark-summary" role="status" aria-live="polite">Complete a generation to capture its timing and browser environment.</p>
<pre id="benchmark-details" class="benchmark-details" tabindex="0"></pre>
</section>
<div class="secondary-actions"><button id="cancel" type="button" disabled>Cancel current operation</button><button id="clear-cache" type="button">Clear cached model files</button></div>
<div id="diagnostics" class="diagnostics" hidden><p id="diagnostic-message"></p><details><summary>Technical details</summary><pre id="diagnostic-details"></pre></details></div>
<p class="privacy-note">Your image stays on this device. Only the manifest and browser-runtime model artifacts are requested from the official <a href="https://huggingface.co/Yosun/TripoSplat-WebGPU/">Hugging Face package</a> unless you explicitly choose a different server. Opaque photos currently need a browser-local background remover; use a transparent PNG or WebP.</p>
</section>
<section id="browser-experiment" class="experiment-panel panel" aria-labelledby="experiment-heading">
<div class="experiment-intro"><span class="section-index">WHY THIS MATTERS</span><h2 id="experiment-heading">A monumental attempt to put CUDA-era 3D generation in reach of more people.</h2></div>
<div class="experiment-copy"><p>TripoSplat started as a CUDA-based 3D generation pipeline. With Codex GPT 5.6 Sol Ultra and GPT 5.6 Sol Max in Kiro, this project is porting that work to WebGPU—replacing the usual requirements for NVIDIA hardware, CUDA, terminal commands, environment setup, and local dependency installation with a browser-native workflow.</p><p>The goal is not a cosmetic port. It is an attempt to make advanced AI 3D generation radically more accessible: for GPUPoor MacBook users, students, independent developers, and anyone without an expensive GPU. When a browser passes the system check, they can generate a 3D asset locally on hardware they already own—no terminal, no installation, and no cloud GPU bill for inference.</p><p>This is still an engineering preview, with compatibility and quality under active qualification. But the direction is clear: keep powerful spatial-generation tools inspectable, local, and available to more builders.</p><a class="github-link" href="https://github.com/yosun/TripoSplatWebGPU" target="_blank" rel="noreferrer">Read the source, benchmarks, and open issues on GitHub <span aria-hidden="true"></span></a></div>
</section>
</main>
<footer><span>TRIPOSPLAT WEBGPU · ENGINEERING PREVIEW</span><a href="#source-heading">Try it out</a><a href="https://github.com/yosun/TripoSplatWebGPU" target="_blank" rel="noreferrer">View source on GitHub <span aria-hidden="true"></span></a><a href="/e2e-lab.html">Qualification lab</a><a href="/sharp-lab.html">Legacy SHARP lab</a></footer>
</body>
</html>