TripoSplat-WebGPU-Demo / e2e-web.html
Yosun's picture
Deploy TripoSplat WebGPU app (staging)
58303f4 verified
Raw
History Blame Contribute Delete
22.2 kB
<!doctype html>
<html lang="en" data-ui-theme="blueprint">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="light" />
<meta name="theme-color" content="#f4f9fc" />
<meta name="application-version" content="0.1.0-preview.8" />
<meta name="application-revision" content="ad54d75a1ffc" />
<meta name="application-environment" content="staging" />
<meta name="application-build-time" content="2026-07-23T05:07:12.137Z" />
<meta name="description" content="Generate a Gaussian splat locally with WebGPU or through the free MutualGPU exchange." />
<meta property="og:type" content="website" />
<meta property="og:title" content="TripoSplat WebRunner · Local WebGPU + MutualGPU" />
<meta property="og:description" content="One image-to-3D runner: use this device or submit to MutualGPU." />
<meta property="og:image" content="https://triposplat-webgpu.vercel.app/corgi.ceo_image_header.social.jpg" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="TripoSplat WebRunner · Local WebGPU + MutualGPU" />
<meta name="twitter:description" content="One image-to-3D runner: use this device or submit to MutualGPU." />
<meta name="twitter:image" content="https://triposplat-webgpu.vercel.app/corgi.ceo_image_header.social.jpg" />
<title>TripoSplat WebRunner · Local + MutualGPU</title>
<link rel="canonical" href="/e2e-web" />
<script type="module" crossorigin src="/assets/e2eWeb-CT1b6ETs.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/preload-helper-BXl3LOEh.js">
<link rel="modulepreload" crossorigin href="/assets/contracts-C1dGGCZV.js">
<link rel="modulepreload" crossorigin href="/assets/triposplat-B2wEwN7F.js">
<link rel="modulepreload" crossorigin href="/assets/webGpuChecks-M0EczEmM.js">
<link rel="modulepreload" crossorigin href="/assets/SplatPreview-D3bCUQ8P.js">
<link rel="stylesheet" crossorigin href="/assets/e2e-web-Djcqrht5.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" aria-label="TripoSplat WebRunner image to 3D">
<span class="brand-mark" aria-hidden="true"><span></span></span><span>TRIPOSPLAT <b>WEBGPU</b></span>
</a>
<div class="topbar-meta">
<button id="ui-theme-toggle" class="ui-theme-toggle" type="button" aria-pressed="true" aria-label="Switch to dark interface">Dark UI <span aria-hidden="true"></span></button>
<span class="app-version" title="Build 2026-07-23T05:07:12.137Z · revision ad54d75a1ffc · environment staging"><b>WEB RUNNER</b> v0.1.0-preview.8 · ad54d75a1ffc · staging</span>
<span class="capability" id="platform-badge"><i></i><span>Checking platform</span></span>
</div>
</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>Local when you can. Mutual when you can’t.</em></h1>
<p>Run the full TripoSplat model on this device when its WebGPU and storage qualify,<br />
or send the same job to a free MutualGPU provider from this page.<br />
Qualified devices can also opt in to help process another person’s TripoSplat job.</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="/learn">Learn how it works <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">YOUR INPUT</span></div>
<p class="panel-copy">Use a transparent PNG or WebP, or prepare an opaque photo locally before generation. The processor removes the background, frames the subject, and creates the official 1024px TripoSplat input.</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>
<section class="image-preparation" aria-labelledby="image-preparation-heading">
<div><span class="section-index">OPTIONAL / LOCAL PROCESSING</span><h3 id="image-preparation-heading">Prepare a photo for TripoSplat</h3></div>
<p>Opaque photos start background removal and the official subject crop automatically in this browser. Your pixels stay on this device; use the button to process again.</p>
<button id="prepare-image" type="button" disabled><span>Process image locally</span><b aria-hidden="true"></b></button>
<p id="image-preparation-status" class="image-preparation-status" data-state="idle" role="status" aria-live="polite">Choose an image to enable local processing.</p>
</section>
<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>
<section class="model-panel panel" aria-labelledby="model-heading">
<div class="panel-heading"><div><span class="section-index">STEP 2 / EXECUTION</span><h2 id="model-heading">Choose where it runs</h2></div><span id="cache-mode" class="local-badge">CHECKING</span></div>
<p class="panel-copy">Use this device for private, browser-local WebGPU generation when it qualifies, or use MutualGPU without local GPU or storage requirements.</p>
<fieldset class="execution-mode" aria-describedby="execution-mode-help">
<legend>Execution mode</legend>
<label data-execution-card="local"><input id="execution-local" type="radio" name="execution-mode" value="local" checked /><span><strong>Run on this device</strong><small id="local-mode-status">Checking WebGPU, model storage, and desktop requirements…</small></span><b>LOCAL</b></label>
<label data-execution-card="mutualgpu"><input id="execution-mutualgpu" type="radio" name="execution-mode" value="mutualgpu" /><span><span class="execution-mode-title"><img src="/assets/mutual-gput-logo-only-flat-white-BLrUD_A9.png" width="40" height="21" alt="" /><strong>Run on MutualGPU</strong></span><small>Use free community-contributed compute. No local WebGPU or 6.5 GB model cache required.</small></span><b>NO LOCAL GPU REQUIRED</b></label>
</fieldset>
<p id="execution-mode-help" class="execution-mode-help">The result returns to this same viewer. Selecting remote mode sends the selected image to the MutualGPU exchange and assigned provider.</p>
<p class="execution-expectation"><strong>Engineering preview.</strong> A first local run may download about 6.5 GB and generation can take several minutes. MutualGPU wait time depends on network, service, and provider availability. Browser support and output quality vary.</p>
<div class="model-layout"><div id="model-status" class="model-status" aria-live="polite">Checking local model storage and MutualGPU configuration…</div></div>
<details id="local-model-settings" class="model-advanced"><summary>Local model server</summary><label for="model-base"><span>Model CDN directory</span><small>Used only for on-device runs and provider work. Must contain manifest.json and allow CORS.</small><input id="model-base" type="url" inputmode="url" autocomplete="url" spellcheck="false" /></label></details>
<details id="mutualgpu-settings" class="model-advanced"><summary>MutualGPU connection</summary><label for="mutualgpu-api-base"><span>MutualGPU HTTPS API</span><small>Defaults to the public MutualGPU exchange. The requestor origin and result storage must allow this application.</small><input id="mutualgpu-api-base" type="url" inputmode="url" autocomplete="url" spellcheck="false" value="https://mutualgpu.com/" /></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 id="mutualgpu-capacity" class="mutualgpu-capacity" role="alert" hidden>
<span>NO COMPUTERS AVAILABLE</span>
<strong>No community computer is available for TripoSplat right now.</strong>
<p>MutualGPU is online, but no TripoSplat provider is currently enrolled. Your image was not processed or queued. Try again shortly, or use the Contribute Compute bar below from a qualified WebGPU device.</p>
<button id="retry-mutualgpu" type="button">Check MutualGPU again</button>
</section>
<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="true">Guided</button><button type="button" data-progress-detail="technical" aria-pressed="false">Technical</button></div></div>
<p id="progress-detail-description" class="progress-detail-description">Guided mode explains each stage in plain language. Technical details remain one click away.</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>
<section id="diagnostics" class="diagnostics" aria-labelledby="diagnostic-heading" hidden>
<div class="diagnostic-heading"><div><span class="section-index">FAILURE DIAGNOSIS</span><h3 id="diagnostic-heading">What likely caused this</h3></div><button id="copy-diagnostics" type="button">Copy diagnostic report</button></div>
<p id="diagnostic-message"></p>
<div class="diagnostic-guidance"><div><strong>Likely cause</strong><p id="diagnostic-cause"></p></div><div><strong>What to try</strong><ol id="diagnostic-actions"></ol></div></div>
<div class="diagnostic-recovery"><button id="retry-generation" type="button">Retry generation</button><button id="use-mutualgpu" type="button">Use MutualGPU instead</button></div>
<details><summary>Technical evidence and runtime event trail</summary><pre id="diagnostic-details" tabindex="0"></pre></details>
</section>
<p class="privacy-note"><strong>Privacy:</strong> local mode keeps image processing and inference on this device. MutualGPU mode uploads the selected image to the exchange and assigned provider. Provider mode receives untrusted requestor images and uses the local model cache. TripoSplat model artifacts come from the official <a href="https://huggingface.co/Yosun/TripoSplat-WebGPU/">Hugging Face package</a> unless you choose another server.</p>
</section>
</div>
<button id="contribute-compute" class="community-compute-bar" type="button" aria-controls="provider-panel" aria-expanded="false" hidden>
<img src="/assets/mutual-gput-logo-only-flat-white-BLrUD_A9.png" width="36" height="19" alt="" />
<span><small>COMMUNITY COMPUTE</small><strong>Contribute Compute on MutualGPU</strong></span>
<b>Share your idle GPU · <span id="contribute-compute-action">More info</span> <span aria-hidden="true"></span></b>
</button>
<details id="provider-panel" class="provider-panel" aria-labelledby="provider-heading">
<summary class="provider-summary flow-heading"><span><span class="section-index">OPTIONAL / SHARE YOUR GPU</span><strong id="provider-heading" class="provider-heading">Become a MutualGPU provider</strong></span><span id="provider-state" class="viewer-state">Checking</span></summary>
<p>Qualified Chrome devices can receive one remote requestor’s TripoSplat assignment at a time. Accepted work runs on this browser and can download the same 6.5 GB model cache while sustaining heavy GPU and power use for several minutes. The requestor identity is not disclosed, but every activity line shows the assignment ID, phase, and progress. The provider key stays in this page’s memory and is never saved. Closing the page interrupts the session. Only enable this in an operator-controlled browser.</p>
<div class="provider-fields">
<label for="provider-key"><span>Provider key</span><small>Issued for one MutualGPU execution unit.</small><input id="provider-key" type="password" autocomplete="off" spellcheck="false" /></label>
<label for="provider-profile"><span>Advertised machine profile</span><small>Choose a profile this device can honestly sustain.</small><select id="provider-profile"><option value="Small:8">Small · 8 GiB</option><option value="Medium:16">Medium · 16 GiB</option><option value="Large:32">Large · 32 GiB</option><option value="ExtraLarge:64">Extra Large · 64 GiB</option></select></label>
</div>
<div class="provider-actions"><button id="start-provider" type="button">Start providing</button><button id="stop-provider" type="button" disabled>Stop</button></div>
<p id="provider-status" class="provider-status" role="status" aria-live="polite">Checking local WebGPU, model, and storage requirements…</p>
<details class="provider-terminal" aria-labelledby="provider-terminal-heading">
<summary class="provider-terminal-heading"><span id="provider-terminal-heading">REMOTE PROVIDER ACTIVITY · LAST 120 EVENTS</span><span class="provider-terminal-toggle" aria-hidden="true"></span></summary>
<div class="provider-terminal-tools"><span id="provider-terminal-copy-status" role="status" aria-live="polite">Select any text, or copy the complete log. New activity never moves your reading position.</span><div class="provider-terminal-actions"><button id="jump-to-provider-terminal-latest" class="provider-terminal-latest" type="button" hidden aria-label="Jump to the latest provider activity" title="Jump to latest activity"><span aria-hidden="true"></span><span>New activity</span></button><button id="copy-provider-terminal" type="button">Copy log</button></div></div>
<pre id="provider-terminal-output" role="log" aria-label="Remote MutualGPU provider activity" aria-live="off" tabindex="0"><span class="provider-terminal-line" data-level="info">Provider is idle. Accepted assignments run on this browser for a MutualGPU requestor; each activity line identifies the remote task.</span></pre>
</details>
</details>
<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/ai3d-dev/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/ai3d-dev/TripoSplatWebGPU" target="_blank" rel="noreferrer">View source on GitHub <span aria-hidden="true"></span></a><a href="https://www.producthunt.com/products/triposplat-webgpu?embed=true&amp;utm_source=badge-featured&amp;utm_medium=badge&amp;utm_campaign=badge-triposplat-webgpu" target="_blank" rel="noopener noreferrer"><img alt="TripoSplat WebGPU - Image to 3D Model: Offline. Local. Portable. | Product Hunt" width="250" height="54" src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1198682&amp;theme=light&amp;t=1784320164461"></a><a href="/e2e-lab.html">Qualification lab</a><a href="/sharp-lab.html">Legacy SHARP lab</a></footer>
</body>
</html>