File size: 7,732 Bytes
1c9a3d9
227cca9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1c9a3d9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
<!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="#111218" />
    <meta
      name="description"
      content="Run Stable Fast 3D locally in your browser with WebGPU."
    />
    <title>Stable Fast 3D · WebGPU</title>
    <link rel="preconnect" href="https://huggingface.co" />
    <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
    <link rel="stylesheet" href="./styles.css" />
    <script type="importmap">
      {
        "imports": {
          "three": "https://cdn.jsdelivr.net/npm/three@0.179.1/build/three.module.js",
          "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.179.1/examples/jsm/"
        }
      }
    </script>
  </head>
  <body>
    <div class="page-shell">
      <header class="topbar">
        <a class="brand" href="https://huggingface.co/" target="_blank" rel="noreferrer">
          <span class="brand-mark">hf</span>
          <span>Hugging Face · Static Space</span>
        </a>
        <div class="topbar-meta">
          <span class="status-dot" id="webgpu-dot"></span>
          <span id="webgpu-label">Checking WebGPU…</span>
        </div>
      </header>

      <main>
        <section class="hero">
          <div class="eyebrow"><span></span> STABLE FAST 3D / BROWSER LAB</div>
          <h1>One image.<br /><em>One mesh.</em></h1>
          <p class="hero-copy">
            Reconstruct a clean, orbit-ready 3D asset from a single image —
            locally, privately, and accelerated by your GPU.
          </p>
          <div class="hero-links">
            <a href="https://huggingface.co/stabilityai/stable-fast-3d" target="_blank" rel="noreferrer">Original model ↗</a>
            <a href="https://huggingface.co/needle-tools/SF3D-webgpu" target="_blank" rel="noreferrer">Browser export ↗</a>
          </div>
        </section>

        <section class="workspace-grid">
          <aside class="control-card card">
            <div class="card-heading">
              <div>
                <span class="section-kicker">01 / INPUT</span>
                <h2>Choose an image</h2>
              </div>
              <span class="mini-badge">512 × 512</span>
            </div>

            <label class="dropzone" id="dropzone" for="image-file">
              <input id="image-file" type="file" accept="image/png,image/jpeg,image/webp" />
              <div class="upload-icon">↑</div>
              <strong>Drop an object image here</strong>
              <span>PNG with transparency works best</span>
              <span class="browse-link">Browse files</span>
            </label>

            <div class="preview-wrap is-hidden" id="preview-wrap">
              <img id="input-preview" alt="Selected input" />
              <div class="preview-label"><span id="preview-name">Input image</span><span id="preview-size"></span></div>
            </div>

            <button class="sample-button" id="sample-button" type="button">
              <span>Try a sample</span><span class="sample-arrow">↗</span>
            </button>

            <label class="toggle-row">
              <span class="toggle-copy">
                <strong>Clean the background</strong>
                <small>Transformers.js · WebGPU</small>
              </span>
              <input id="remove-background" type="checkbox" checked />
              <span class="toggle-ui"></span>
            </label>

            <div class="tip-box">
              <span class="tip-icon">✦</span>
              <span>Use one centered object with good contrast. Transparent PNGs skip the cleanup model.</span>
            </div>

            <button class="primary-button" id="generate-button" type="button" disabled>
              <span id="generate-label">Select an image</span>
              <span class="button-arrow">→</span>
            </button>
          </aside>

          <section class="viewer-card card">
            <div class="viewer-head">
              <div>
                <span class="section-kicker">02 / OUTPUT</span>
                <h2>Inspect your mesh</h2>
              </div>
              <span class="live-badge"><i></i> LOCAL INFERENCE</span>
            </div>
            <div class="viewer-stage" id="viewer-stage">
              <canvas id="viewer-canvas" aria-label="3D mesh viewer"></canvas>
              <div class="viewer-empty" id="viewer-empty">
                <div class="empty-orbit">◎</div>
                <strong>Your mesh will appear here</strong>
                <span>Drag to orbit · scroll to zoom</span>
              </div>
              <div class="viewer-progress is-hidden" id="viewer-progress">
                <div class="progress-ring"><span id="progress-percent">0%</span></div>
                <strong id="progress-title">Preparing pipeline</strong>
                <span id="progress-detail">The first run downloads the model into your browser cache.</span>
              </div>
              <div class="viewer-error is-hidden" id="viewer-error">
                <div class="error-icon">!</div>
                <strong id="error-title">Something went wrong</strong>
                <span id="error-detail"></span>
                <button id="error-dismiss" type="button">Dismiss</button>
              </div>
              <div class="viewer-toolbar">
                <button id="reset-view" type="button" title="Reset camera">Reset view</button>
                <span id="mesh-stats">No mesh loaded</span>
              </div>
            </div>
            <div class="viewer-foot">
              <div class="metric"><span>RUNTIME</span><strong id="runtime-metric">—</strong></div>
              <div class="metric"><span>VERTICES</span><strong id="vertices-metric">—</strong></div>
              <div class="metric"><span>FACES</span><strong id="faces-metric">—</strong></div>
              <button class="download-button" id="download-button" type="button" disabled>
                Download GLB <span>↓</span>
              </button>
            </div>
          </section>
        </section>

        <section class="how-section">
          <div class="section-heading-row">
            <div>
              <span class="section-kicker">03 / UNDER THE HOOD</span>
              <h2>Private by design</h2>
            </div>
            <p>No image leaves this tab. Models are fetched once, then cached by your browser.</p>
          </div>
          <div class="steps-grid">
            <article class="step-card">
              <span class="step-number">01</span>
              <div class="step-icon">◌</div>
              <h3>Prepare</h3>
              <p>Optional foreground cleanup runs with Transformers.js on WebGPU.</p>
            </article>
            <article class="step-card step-accent">
              <span class="step-number">02</span>
              <div class="step-icon">⌁</div>
              <h3>Reconstruct</h3>
              <p>SF3D’s ONNX graphs predict a triplane and decode its surface locally.</p>
            </article>
            <article class="step-card">
              <span class="step-number">03</span>
              <div class="step-icon">◇</div>
              <h3>Explore</h3>
              <p>Orbit the mesh, inspect its topology, and export a portable GLB.</p>
            </article>
          </div>
        </section>
      </main>

      <footer class="footer">
        <span>Powered by Stability AI · Stable Fast 3D Community License</span>
        <span>WebGPU / Transformers.js / ONNX Runtime Web</span>
      </footer>
    </div>

    <script type="module" src="./src/main.js"></script>
  </body>
</html>