Gemini 4 Argon Three.js: What 105 3D Scenes Show, Plus Our Run
Gemini 4 Argon Three.js scenes: what 105 launch-week 3D posts show, then our own single-file run on SandBase with tokens, cost, render checks and what broke.

Our Gemini 4 Argon scene loaded on the first try, logged zero page errors, and drew snow, stars, a moon and an aurora. The telescope was missing. It was in the code, about 30 lines of it, but it sat inside the dome and pointed at a solid wall. You only find that kind of bug if you render the file and look at it from more than one angle.
This is a field guide to Gemini 4 Argon Three.js work for developers who want a browser 3D scene from one prompt. Part one reads the 105 3D-scene posts in SandBase Lab’s launch-week collection. Part two is our own run through SandBase: one specified prompt, one fix prompt, headless Chrome checks, and the bill.
Key takeaway
- 105 of the 264 Argon videos in SandBase Lab’s collection are 3D scenes. 52 of those posts are framed as comparisons (a rival model, “vs” or “same prompt”); Claude Opus 5.5 is named in 44.
- At least 47 of the 105 mention Three.js, WebGL or HTML, and 12 mention Blender or a Blender-like tool. Several of the most polished results came from agent loops, not one prompt.
- Our 15-point single-file prompt returned 587 lines of HTML in 57 s for $0.1507 (715 in / 7,393 out tokens). It met 14 of 15 requirements; the telescope failed.
- One fix prompt for four named bugs cost $0.1910 and fixed three. The fourth, a sawtooth seam, survived both Argon’s fix and a shadow tweak we tried by hand.
- SandBase lists Argon at $4 / $20 per million tokens, twice Google’s introductory direct rate, which runs until Nov 30, 2026.
What the 105 Gemini 4 Argon 3D scene posts show
The data is the SandBase Lab Gemini 4 Argon collection, synced 2026-10-14 16:29 UTC: 264 public X videos from October 13 and 14, 2026, of which 105 are tagged 3d-scene, from 88 creators. They drew 13,400 likes and about 1.46M views. The median 3D post has 27 likes, against 21 for the whole set. Google’s launch post says Googlers use Argon for “complex 3D visualizations, high-fidelity games, and interactive animations in vanilla code”, so this is a use case Google is pitching.
The counts are keyword matches on post text, spot-read by me. A post can sit in two rows.
| What the post is about | Posts (keyword match) | Examples |
|---|---|---|
| Vehicles and machines | 27 | F1 cars, helicopters, a turbofan, a clockwork bee |
| Buildings and cities | 26 | Himeji Castle, a Roman city, New York, a room designer |
| Creatures and characters | 28 | gummy bears, a whale, dragons, a Shiba Inu |
| Landscapes and water | 14 | islands, a forest, a storm-lashed lighthouse |
| Space | 7 | a solar system tour, a galaxy, a black hole |
The tool split matters more than the subject. At least 47 posts name Three.js, WebGL or an HTML file. 12 name Blender, Mixar (a Blender fork) or Autodesk Fusion, and 6 are robotics simulations. A Blender agent loop and a single HTML file share the bucket but are different jobs.
Single-file HTML is the common format
15 posts say the result is one HTML file. Several give numbers:
- @SidraMiconi (Lab): one call, high thinking, “Third try: 363 in, 6,387 thinking, 18,359 out tokens, 25 cents, 4.4 min.”
- @analogalok (Lab): a navigable forest from a one-line prompt, 27k tokens, $0.27 at $2 / $10.
- @YFarmX (Lab): a lighthouse, “~87k tokens across the whole chat”, about 36 cents.
- @alwayspriyesh (Lab): a room designer, one prompt, about 2 minutes, “barely $1”.
- @mizugame_22 (Lab): a Shiba Inu with no library at all; the creator (writing in Japanese) says Argon wrote its own Three.js-like parts and 24 fur shells.
![]()
A Lab detail page keeps the creator’s own token and cost figures next to the clip; this one reports a third attempt at 18,359 output tokens and 25 cents (captured 2026-10-14 UTC). The figures are the creator’s, not ours.
These are creator statements at each creator’s price, but they set an expectation: roughly 7k to 30k output tokens per answer, and often a “third try”.
Physics and voxels are where comparisons get sharp
Physics posts show the clearest failures. @semichenkko’s gummy-bear test, the top 3D post at 3,937 likes, found Argon’s bears turned into “gummy statues”. @LeeLinAI123 ran the same moves on capybaras and got “standing capybara sheets”. @elliscrosby reports an ice-swan carving where “the finished swan never shows up because its webgl shader is broken”. Soft bodies and shaders break visibly, which makes them good tests.
Voxel art is the opposite: simple geometry, easy to judge. Nine posts are voxel scenes. @noclipepe posted the whole prompt: “Create a pelican doing a wheelie on top of a flying fighter jet. Voxel artstyle. Single HTML.” @Avenoxai had Claude Sonnet 5.5 and Argon build a voxel Hagia Sophia block by block in one HTML file (23,782 blocks against 23,177). @filicroval says Argon “still gets mogged by sonnet 5.5 on the same voxel prompt”.
Comparisons are single runs, and the fanciest results were iterated
About half the posts bring in a rival model; 40 are explicit head-to-heads under the launch-week data study’s stricter rule. The cost gaps they report are large: @luckeyfaraday has one Mario 3D run at 6 minutes and $1.16 and the other at 26 minutes and $4.89; @0xRhinoX reports a firefly jar at $0.19 for Argon and $15.00 for Opus 5.5, while conceding Opus “made real glass”. Each is one creator’s single run. @NicolaManzini cites threejseval, a blind-vote Three.js leaderboard, with Argon at #7 after a day; we haven’t checked it.
The best-looking scenes often weren’t one-shots. @thtbee_’s battle helicopter came from “multi round self iteration loop of Argon + Nano Banana”. @shiri_shh’s Blender pagoda used one agent to build and another to critique the render, and @JustLingonberry pushed back that it “DID NOT one shot this”. If a post doesn’t say how many turns it took, assume more than one. The 20 most-liked Argon examples covers the top 3D clips.
Our run: one single-file Three.js prompt to Argon on SandBase
I wanted parts that are easy to check: an observatory on a snowy ridge, a rotating dome with a slit and telescope, 3,000 stars, an aurora shader, 1,500 snowflakes, camera limits and a test hook. Two choices came from the posts above: pin everything the browser loads, and make the page report on itself.
One check shaped the prompt first. From our network on 2026-10-14, cdn.jsdelivr.net reset the connection while unpkg.com returned HTTP 200. An unpinned prompt lets the model pick the CDN, so I pinned it.
Build a single-file Three.js scene: a small astronomical observatory on a snowy mountain ridge at night.
Hard constraints
1. Reply with one complete index.html and nothing else: no explanation, no markdown fences.
2. Load Three.js only through this importmap, exactly:
"three": "https://unpkg.com/[email protected]/build/three.module.js"
"three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
No other network requests. No external textures, models, fonts or images; everything is procedural.
3. No Math.random. Use a seeded PRNG (mulberry32, seed 42) so the scene is identical on every load.
4. The page must run with zero console errors or warnings, from a static file server.
Scene
5. Terrain: a ridge built from a PlaneGeometry displaced with seeded value noise, snow-white with subtle blue shading, receiving shadows.
6. Observatory on the ridge top: a cylindrical base, a hemispherical dome with a visible vertical slit, and a telescope tube poking out of the slit. The dome rotates slowly around Y (about one turn per 60 s) and the telescope rotates with it.
7. A warm-lit doorway on the base (small emissive plane plus a PointLight) so the building reads at night.
8. Sky: 3,000 stars as THREE.Points on a large sphere, slowly rotating around a tilted axis; a faint moon (emissive sphere) and a DirectionalLight from the moon direction casting soft shadows (PCFSoftShadowMap, 2048 map).
9. Aurora: one or two curved ribbon meshes using a custom ShaderMaterial with a time uniform, additive blending, green-to-violet gradient, gently waving.
10. Snowfall: 1,500 particles as THREE.Points that fall, drift with a little wind and wrap around when they reach the ground.
Camera and rendering
11. PerspectiveCamera fov 50, starting slightly below and to the side of the dome so the aurora is visible behind it. OrbitControls with damping, target on the dome, minDistance 8, maxDistance 80, and a maxPolarAngle that keeps the camera above the terrain.
12. WebGLRenderer with antialias, pixel ratio capped at 2, ACESFilmicToneMapping, SRGBColorSpace output, shadows on, and a window resize handler.
13. Use THREE.Clock for animation timing.
HUD and test hooks
14. A small top-left overlay (plain HTML/CSS) with the title "Ridge Observatory" and a live FPS counter.
15. After the first frame has rendered, set window.__sceneReady = true and console.log one line: JSON.stringify({ready: true, meshes: <number of Mesh objects in the scene>, points: <number of Points objects>, triangles: renderer.info.render.triangles}).
Before you answer, check your file against every numbered requirement above and fix anything missing. Keep the file under about 600 lines.
The pipeline: generate, save, bill, render
prompt.txt ──> argon_scene.py ──POST /v1/chat/completions──> google/gemini-4-argon
│ save <tag>.html + usage (SandBase, OpenAI-compatible)
└─ GET /v1/tasks/<id>/cost ──> billed USD
<tag>.html ──> python3 -m http.server ──> render.mjs (headless Chrome)
└─ console + pageerror + network log, __sceneReady wait, screenshots
The generator is plain Python over the Chat Completions API. It retries rate limits, 5xx and timeouts (Google’s model card lists “occasional slowness or timeout issues”), refuses a truncated answer, and asks the cost endpoint what was billed:
"""Ask Gemini 4 Argon (via SandBase) for a single-file Three.js scene, save the HTML, record usage and billed cost.
usage: python3 argon_scene.py <tag> [messages.json]
without messages.json the prompt is read from prompt.txt
"""
import datetime
import json
import os
import re
import sys
import time
import requests
BASE = "https://api.sandbase.ai/v1"
HEADERS = {"Authorization": "Bearer " + os.environ["SANDBASE_API_KEY"]}
MODEL = "google/gemini-4-argon"
RETRY_STATUS = {429, 500, 502, 503, 504}
def chat(messages, max_tokens=32000, attempts=3):
"""POST /v1/chat/completions with retries on rate limits, 5xx and timeouts."""
body = {"model": MODEL, "max_tokens": max_tokens, "messages": messages}
for attempt in range(1, attempts + 1):
try:
t0 = time.time()
r = requests.post(f"{BASE}/chat/completions", headers=HEADERS, json=body, timeout=1200)
if r.status_code in RETRY_STATUS and attempt < attempts:
time.sleep(10 * attempt)
continue
r.raise_for_status()
return body, r.json(), round(time.time() - t0, 1)
except (requests.Timeout, requests.ConnectionError):
if attempt == attempts:
raise
time.sleep(10 * attempt)
raise RuntimeError("unreachable")
def extract_html(content):
"""Keep the HTML even if the model wraps it in a markdown fence despite being told not to."""
fenced = re.search(r"```(?:html)?\s*\n(.*?)```", content, re.S)
html = fenced.group(1) if fenced else content
if "<html" not in html.lower() and "<!doctype html" not in html.lower():
raise RuntimeError("response does not contain an HTML document")
return html
def billed_cost(completion_id):
"""GET /v1/tasks/<id>/cost; settlement can lag a few seconds."""
for _ in range(5):
c = requests.get(f"{BASE}/tasks/{completion_id}/cost", headers=HEADERS, timeout=60)
if c.ok and c.json().get("settled"):
return c.json()["cost"]
time.sleep(3)
return None
def main():
tag = sys.argv[1]
if len(sys.argv) > 2:
messages = json.load(open(sys.argv[2]))
else:
messages = [{"role": "user", "content": open("prompt.txt").read()}]
started = datetime.datetime.now(datetime.timezone.utc).isoformat()
body, resp, elapsed = chat(messages)
json.dump({"request": body, "response": resp}, open(f"{tag}.raw.json", "w"), indent=1)
choice = resp["choices"][0]
if choice.get("finish_reason") == "length":
raise RuntimeError("output hit max_tokens; the HTML is truncated")
html = extract_html(choice["message"].get("content") or "")
open(f"{tag}.html", "w").write(html)
record = {"started_utc": started, "elapsed_s": elapsed, "id": resp["id"],
"usage": resp.get("usage"), "cost_usd": billed_cost(resp["id"]),
"html_lines": html.count("\n") + 1}
json.dump({"request": body, "response": resp, **record}, open(f"{tag}.json", "w"), indent=1)
print(json.dumps(record))
if __name__ == "__main__":
main()
The two scene calls used an earlier version with the same request body and no retry loop. I ran this final version on a tiny HTML prompt, and the smoke test caught a bug in my own code: Argon returned a valid HTML5 document with no <html> tag, which my first check rejected.
The render check uses Playwright with the local Chrome and SwiftShader software WebGL. It logs console messages, page errors and network requests, waits for __sceneReady, and screenshots. A second script drags, zooms and tries to push the camera under the terrain.
// Render a generated scene in headless Chrome, collect console output, take screenshots.
import { chromium } from 'playwright-core';
const [, , url, out] = process.argv;
const b = await chromium.launch({ channel: 'chrome', args: ['--use-angle=swiftshader', '--enable-unsafe-swiftshader', '--ignore-gpu-blocklist'] });
const p = await b.newPage({ viewport: { width: 1280, height: 720 }, deviceScaleFactor: 1 });
const log = [];
p.on('console', m => log.push({ type: m.type(), text: m.text().slice(0, 400) }));
p.on('pageerror', e => log.push({ type: 'pageerror', text: String(e).slice(0, 400) }));
p.on('requestfailed', r => log.push({ type: 'requestfailed', text: r.url() + ' ' + (r.failure()?.errorText || '') }));
const reqs = [];
p.on('request', r => reqs.push(r.url()));
const t0 = Date.now();
await p.goto(url, { waitUntil: 'load', timeout: 60000 });
let ready = false;
try { await p.waitForFunction(() => window.__sceneReady === true, null, { timeout: 45000 }); ready = true; } catch { }
const readyMs = Date.now() - t0;
await p.waitForTimeout(4000);
await p.screenshot({ path: `${out}-a.png` });
await p.waitForTimeout(6000);
await p.screenshot({ path: `${out}-b.png` });
const info = await p.evaluate(() => ({ ready: window.__sceneReady, w: innerWidth, h: innerHeight, hud: document.body.innerText.slice(0, 200) }));
console.log(JSON.stringify({ ready, readyMs, info, requests: [...new Set(reqs)].filter(u => !u.startsWith('http://127.0.0.1')), log }, null, 1));
await b.close();
Run 1: 14 of 15 requirements on the first answer
Run 1 started at 18:57:46 UTC on 2026-10-14, with max_tokens 32000 and no other parameters. It returned in 57.0 s with finish_reason: stop: 715 prompt tokens, 7,393 completion tokens, 0 reasoning tokens. GET /v1/tasks/a1dc1cf8-b69a-4cb4-91fb-28a3bd139a93/cost billed $0.150720, exactly 715 × $4/M + 7,393 × $20/M. The answer was 587 lines of raw HTML, no fence.
In Chrome, __sceneReady turned true after 4.0 s and the page logged {"ready":true,"meshes":18,"points":2,"triangles":98034}. The only requests were the two pinned unpkg files. The only console error was our static server’s /favicon.ico 404; the warnings were GPU-stall notices from our own screenshots.

The default camera view of the final file at 1280×720 in headless Chrome: terrain, lit doorway, aurora shader, moon, stars, snow and the HUD all render (captured 2026-10-14, UTC). This is the run 2 file; from this angle run 1 looks nearly identical, apart from square snowflakes.
Against the 15 requirements: mulberry32 with seed 42, no Math.random, and the camera couldn’t be dragged below the ridge. The miss was item 6, the telescope. The code showed why. The tube’s tip ended inside the dome’s 3.15-unit radius, and it tilted toward +X while the slit sat on −X, because THREE.SphereGeometry starts phi on the −X axis. A self-check pass won’t catch that, because the code reads correctly.
Two smaller issues weren’t violations: snow and stars drew as hard squares, and at full zoom a sawtooth seam ran under the dome ring.
Run 2: one fix prompt, three of four fixes landed
The fix went in as a second turn: the original prompt, Argon’s full answer, and a message naming four problems with my diagnosis of each, ending in “change nothing else”. It started at 19:02:09 UTC, took 55.4 s, used 8,315 prompt and 7,888 completion tokens, and was billed $0.191020. The 617-line file passed the same console and network check.

Same mouse drag on both files: run 1 shows a slit with nothing in it; after the fix prompt the tube pokes out of the dome (captured 2026-10-14, UTC).
The telescope fix worked, and so did round sprites on a CanvasTexture with depthWrite off. The seam didn’t change. I had called it z-fighting; Argon edited the ring and base, and the pattern stayed. Adding shadow.normalBias = 0.05 by hand to a local copy didn’t remove it either. My guess is the ring’s shadow edge on a 2048 shadow map stretched over a large scene, unconfirmed. That one is on me: a fix prompt is only as good as the diagnosis inside it.

The seam that survived the fix prompt, zoomed in on run 2 (captured 2026-10-14, UTC). The cause is unconfirmed; a shadow normal-bias tweak didn’t remove it.
The FPS counter read 16 to 20, which reflects software rendering; we didn’t test on a GPU.

Usage from the response bodies and settled cost from /v1/tasks/<id>/cost for both calls, with the run 1 console and network log; rendered from our own run records.
Cost of a Gemini 4 Argon Three.js scene
SandBase lists Argon at $4 input / $20 output per million tokens, cached reads at 5% of input. That is Google’s post-November-30 standard rate and twice its introductory direct price; the pricing guide covers the date change. Output dominates: in run 1, 98% of the bill was output tokens.
| Item | Our run on SandBase | Same tokens at Google’s intro $2 / $10 |
|---|---|---|
| Run 1, first answer | $0.1507 | $0.0754 |
| Run 2, fix turn | $0.1910 | $0.0955 |
| One scene + one fix | $0.3417 | $0.1709 |
| 100 scenes a month, one fix each | about $34 | about $17 |
| 1,000 scenes a month | about $342 | about $171 |
The monthly rows assume every scene looks like ours; a 30k-token scene costs about four times as much. The fix turn resends the first answer as input, and cached_tokens was 0, so it was billed at full input price.
All Argon calls for this article were billed $0.3458 across five recorded calls (two scene calls, two arithmetic probes, one smoke test), plus one unlogged smoke call of the same tiny size.
A reusable prompt pattern for Three.js scenes
- Deliverable and format. One file, no prose, no fences; the extractor should still handle fences.
- Pinned dependencies. An exact importmap with a version and a CDN you’ve checked from where the page runs. Forbid other requests.
- Determinism. A seeded PRNG, so renders match and bugs reproduce.
- Numbered requirements, each checkable from a screenshot or the code: counts, lights, map sizes, speeds.
- Camera limits. Distances and a polar-angle cap.
- A test hook. A ready flag and a one-line JSON log for the headless browser.
- A self-check instruction. Cheap, but it missed the geometry bug, so render anyway.
For the fix turn, name each defect, state what you observed rather than only your guess, and say “change nothing else”. For more variants, see the Argon creative-coding prompt guide. If the scene needs input and a game loop, the one-prompt browser game piece tests that separately.
FAQ
Can Gemini 4 Argon write a working Three.js scene in one prompt?
In our run it produced a file that loaded with no page errors and met 14 of 15 written requirements on the first answer. One visible part, the telescope, was wrong, and one fix turn repaired it. Many creators in the Lab collection report needing two or three tries.
How much does a Gemini 4 Argon Three.js scene cost?
Ours cost $0.1507 for the first answer and $0.3417 including one fix, at SandBase’s $4 / $20 list price. Our answer was 7,393 output tokens; creators in the collection report 18k to 28.5k output tokens for single answers, which is about $0.36 to $0.57 of output at $20 per million.
Did Argon use reasoning tokens for the scene?
Both scene calls reported reasoning_tokens: 0. Two small arithmetic probes the same evening reported 81 and 60; one of them sent reasoning_effort: "high", which the API accepted without error. We didn’t set a reasoning parameter for the scene calls and don’t know how SandBase’s default maps to Google’s effort levels.
Is the SandBase price the same as Google’s?
No. SandBase lists $4 / $20 per million tokens. Google charges $2 / $10 direct until November 30, 2026, then $4 / $20.
Limits of this test
One prompt, one fix turn, one scene, software WebGL in headless Chrome on a Mac. Nothing here measures GPU frame rate, other browsers, or how often Argon gets the same scene right. The Lab statistics are keyword counts over a curated set of X posts, and creator figures are their claims. Argon’s earlier preview coverage predates general availability, and the launch-week data study covers the whole collection. To run the same prompt yourself, the Gemini 4 Argon model page lists the model ID and current price.