Gemini 4 Argon Three.js 3D 场景实测:105 个作品看门道,再自己跑一次
用 Gemini 4 Argon 写 Three.js 3D 场景:先拆解发布周 105 个 3D 作品,再在 SandBase 上实跑一个单文件场景,记录 token、费用、渲染检查和翻车点。

我们让 Gemini 4 Argon 写的 3D 场景,第一次打开就跑起来了:页面零报错,雪、星空、月亮、极光一样不少。偏偏望远镜不见了。代码里明明有,30 来行,可它整个藏在圆顶里面,还朝着一堵实心墙。这种 bug 不渲染、不换几个角度看,根本发现不了。
这篇写给想用 Gemini 4 Argon 写 Three.js 3D 场景的开发者。前半部分拆解 SandBase Lab 发布周合集里 105 个 3D 场景作品:大家做了什么、用什么工具链、哪些说法只是“同题对比”而不是测量。后半部分是我们自己的实测:在 SandBase 上发一个写得很细的单文件 prompt,再发一轮修复,用无头 Chrome 检查,最后算账。
先说结论
- SandBase Lab 合集里 264 个 Argon 视频,有 105 个是 3D 场景。其中 52 条是对比帖(点名别的模型,或写了“vs”“same prompt”),点名 Claude Opus 5.5 的有 44 条。
- 105 条里至少 47 条提到 Three.js、WebGL 或 HTML,12 条提到 Blender 一类工具。效果最精致的几个,不少是 agent 多轮迭代出来的,不是一次出图。
- 我们 15 条要求的单文件 prompt,57 秒返回 587 行 HTML,花费 $0.1507(输入 715、输出 7,393 token),满足 14 条,望远镜那条没做到。
- 一轮修复 prompt 点名 4 个问题,花费 $0.1910,修好 3 个。剩下那条锯齿接缝,Argon 没修掉,我手动调阴影参数也没修掉。
- SandBase 上 Argon 标价每百万 token $4 输入 / $20 输出,是 Google 直连优惠价的两倍;优惠价到 2026 年 11 月 30 日为止。
105 个 Gemini 4 Argon 3D 场景作品在做什么
数据来自 SandBase Lab 的 Gemini 4 Argon 合集,同步时间 2026-10-14 16:29 UTC,收录 10 月 13、14 日两天 X 上的 264 个公开视频。其中标为 3d-scene 的有 105 个,来自 88 位创作者,合计 13,400 赞、约 146 万次观看。3D 作品的点赞中位数是 27,全合集是 21。Google 在发布文章里也说,内部员工用 Argon 做复杂 3D 可视化、高保真游戏和原生代码动画。这正是 Google 主推的场景之一。
下面的数字是对帖子正文做关键词匹配、再人工抽读得出的,一条帖子可能同时落在两行。
| 题材 | 帖子数(关键词匹配) | 例子 |
|---|---|---|
| 载具和机械 | 27 | F1 赛车、直升机、涡扇发动机、发条蜜蜂 |
| 建筑和城市 | 26 | 姬路城、罗马城、纽约、房间设计器 |
| 生物和角色 | 28 | 软糖熊、鲸鱼、龙、柴犬 |
| 地貌和水 | 14 | 海岛、森林、暴风雨中的灯塔 |
| 太空 | 7 | 太阳系漫游、星系、黑洞 |
比题材更关键的是工具链。至少 47 条点名 Three.js、WebGL 或 HTML 文件;12 条点名 Blender、Mixar(一个 Blender 分支)或 Autodesk Fusion;另有 6 条是机器人仿真。Blender 里跑 agent 循环和写一个 HTML 文件,虽然都归在“3D 场景”,其实是两类活。
单 HTML 文件是最常见的交付形态
明确说成品是一个 HTML 文件的有 15 条。有几条给了数字,可以当参照:
- @SidraMiconi(Lab 页):一次调用、high thinking,第三次尝试用了 363 输入、6,387 思考、18,359 输出 token,25 美分,4.4 分钟。
- @analogalok(Lab 页):一句话 prompt 做出可漫游的森林,27k token,按 $2 / $10 算 $0.27。
- @YFarmX(Lab 页):暴风雨灯塔,整段对话约 87k token,约 36 美分。
- @alwayspriyesh(Lab 页):交互式房间设计器,一次 prompt,约 2 分钟,不到 1 美元。
- @mizugame_22(Lab 页):一只柴犬,不引任何库。作者说 Argon 自己手写了类似 Three.js 的部件,毛发用 24 层壳来画。
![]()
Lab 详情页把创作者自己报的 token 和费用放在视频旁边:这一条是第三次尝试,输出 18,359 token,25 美分(2026-10-14 UTC 截图)。数字是创作者的说法,不是我们测的。
这些都是创作者自述,价格口径也各不相同。但它们给了一个大致预期:单文件场景一次回答大约 7k 到 30k 输出 token,而且经常是“第三次才成”。
物理和体素,是对比最见真章的地方
物理类帖子最容易看出翻车。点赞最高的 3D 帖子是 @semichenkko 的软糖熊测试(3,937 赞),作者的结论是 Argon 做出来的不是软糖,是“软糖雕像”。@LeeLinAI123 用同一套动作测水豚,Argon 的水豚成了立着的纸片。@elliscrosby 的冰雕天鹅,前面电锯、凿子都做了,最后天鹅没出来,因为 WebGL shader 坏了。软体和 shader 一坏就看得见,所以拿来当测试题很合适。
体素正好相反:几何简单,好坏一眼看清。体素题材有 9 条。@noclipepe 把完整 prompt 贴了出来,就一句:鹈鹕在飞行中的战斗机上翘头,体素风格,单个 HTML。@Avenoxai 让 Claude Sonnet 5.5 和 Argon 在一个 HTML 文件里一块块搭体素版圣索菲亚大教堂,分别用了 23,782 和 23,177 块。@filicroval 则说,同一个体素 prompt,Argon 还是被 Sonnet 5.5 压了一头。
对比视频都是单次,最精致的作品多半迭代过
约一半帖子把别的模型拉进来比;按发布周数据研究那套更严的规则,明确同题对比的是 40 条。报出来的成本差距很大。@luckeyfaraday 的 Mario 3D 测试,一个 6 分钟 $1.16,另一个 26 分钟 $4.89;@0xRhinoX 的萤火虫罐子,Argon $0.19、Opus 5.5 $15.00,但作者也承认 Opus 做出了真正的玻璃质感。每一条都只是某个人跑了一次。@NicolaManzini 提到一个盲投的 Three.js 排行榜 threejseval,说 Argon 一天后排第 7。这是众投结果,我们没核实。
效果最好的那批,往往不是一次出来的。@thtbee_ 的战斗直升机,是 Argon 加 Nano Banana 多轮自我迭代的结果。@shiri_shh 的 Blender 宝塔,一个 agent 负责搭,另一个看渲染图挑毛病;@JustLingonberry 专门出来澄清:这不是一次生成的。帖子没写跑了几轮,就默认不止一轮。热门 3D 作品的更多细节见 Argon 最受欢迎的 20 个作品。
我们的实测:在 SandBase 上发一个单文件 Three.js prompt
我想要一个每个部件都好检查的场景:雪山脊上的天文台,圆顶带开缝、会转,里面伸出望远镜,3,000 颗星,极光 shader,1,500 片雪,相机有边界,外加测试钩子。从前面那些帖子里学到两件事:浏览器加载的东西全部钉死;让页面自己报告状态。
发 prompt 之前还先踩了一个坑。2026-10-14 在我们的网络里,cdn.jsdelivr.net 直接被重置连接,unpkg.com 返回 HTTP 200。如果不指定 CDN,模型可能选到 jsdelivr,页面就白屏了。所以 prompt 里把 CDN 和版本都写死。prompt 原文是英文,下面照原样贴出:
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.
流程:生成、保存、对账、渲染
prompt.txt ──> argon_scene.py ──POST /v1/chat/completions──> google/gemini-4-argon
│ 保存 <tag>.html 和 usage (SandBase, OpenAI 兼容)
└─ GET /v1/tasks/<id>/cost ──> 实际扣费
<tag>.html ──> python3 -m http.server ──> render.mjs(无头 Chrome)
└─ console、pageerror、网络请求日志,等 __sceneReady,截图
生成脚本走 SandBase 的 Chat Completions API,用普通 Python 写。它会对 429、5xx 和超时做重试(Google 的模型卡明确写了偶尔会慢或超时),遇到 finish_reason: length 直接报错,最后去 cost 接口查实际扣费:
"""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()
两次场景调用用的是这个脚本的早期版本:请求体完全一样,只是没有重试循环。重试和 doctype 判断是后来加的,最终版用一个很小的 HTML prompt 跑过。这次冒烟测试还抓到了我自己的 bug:Argon 返回了一个合法的 HTML5 文档,但没有 <html> 标签,我第一版的检查把它误判成失败。
渲染检查用 Playwright 驱动本机 Chrome,WebGL 走 SwiftShader 软件渲染。脚本记录 console、页面异常和所有网络请求,等 __sceneReady 变成 true 后截图。另一个脚本负责拖动视角、滚轮缩放,还会试着把相机拖到地面以下。
// 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();
第一轮:15 条要求做到 14 条
第一轮在 2026-10-14 18:57:46 UTC 发出,只设了 max_tokens 32000。57.0 秒后返回,finish_reason: stop,输入 715 token、输出 7,393 token,reasoning token 为 0。GET /v1/tasks/a1dc1cf8-b69a-4cb4-91fb-28a3bd139a93/cost 显示扣费 $0.150720,正好等于 715 × $4/M + 7,393 × $20/M。返回内容是 587 行纯 HTML,没有包代码块。
在 Chrome 里,4.0 秒后 __sceneReady 变成 true,页面打印出 {"ready":true,"meshes":18,"points":2,"triangles":98034}。网络请求只有钉死的两个 unpkg 文件。console 里唯一的 error 是我们本地静态服务器的 /favicon.ico 404;几条 warning 是我们截图时读像素引起的 GPU stall 提示,和页面本身无关。

最终文件在无头 Chrome 中以 1280×720 渲染的默认视角:地形、门口灯光、极光 shader、月亮、星空、雪和 HUD 都正常(2026-10-14 UTC 截图)。这是第二轮的文件;从这个角度看,第一轮几乎一样,只是雪花是方块。
逐条对照 15 条要求:随机数用的是 mulberry32、种子 42,全文没有 Math.random;相机也拖不到地面以下。没做到的是第 6 条,望远镜。读代码才知道原因:镜筒末端落在圆顶 3.15 的半径以内,从外面根本看不见;而且镜筒朝 +X 倾斜,开缝却开在 −X,因为 THREE.SphereGeometry 的 phi 角是从 −X 轴开始算的。这种几何约定上的错,让模型自查是查不出来的,代码读起来完全合理。
另外两个小问题不算违规:雪花和星星画成了硬边方块;放大到最近时,圆顶环下面有一圈锯齿状接缝。
第二轮:一轮修复,4 个问题修好 3 个
修复作为第二轮对话发出:原 prompt、Argon 的完整回答,加一条消息,逐条写明 4 个问题和我的判断,最后要求“其他一律不改”。这一轮 19:02:09 UTC 发出,耗时 55.4 秒,输入 8,315、输出 7,888 token,扣费 $0.191020。新文件 617 行,console 和网络检查同样通过。

两个文件做同样的鼠标拖动:第一轮开缝里空空如也,修复后镜筒从圆顶伸了出来(2026-10-14 UTC 截图)。
望远镜修好了,雪花和星星也换成了画在 CanvasTexture 上的圆形柔边贴图,并关掉了 depthWrite。接缝没变。我当时判断是 z-fighting,Argon 照着改了圆环和底座,锯齿还在。我又手动在本地副本里加了 shadow.normalBias = 0.05,也没消掉。我猜是圆环的阴影边缘落在一张覆盖整个大场景的 2048 阴影贴图上,精度不够,但没有验证。说白了这一条锅在我:修复 prompt 的效果,取决于里面的诊断对不对。

修复后仍然存在的锯齿接缝,第二轮文件放大截图(2026-10-14 UTC)。原因未确认,调整阴影 normalBias 也没有消除。
整个过程 FPS 计数在 16 到 20 之间,这是软件渲染的水平;我们没在 GPU 上测。

两次调用的 usage 来自响应体,扣费来自 /v1/tasks/<id>/cost 的结算结果,下方附第一轮的 console 和网络日志;由我们自己的运行记录渲染而成。
用 Gemini 4 Argon 做一个 Three.js 场景要花多少钱
SandBase 上 Argon 的标价是每百万 token $4 输入、$20 输出,缓存读取按输入价的 5% 计。这是 Google 11 月 30 日之后的标准价,也是它当前直连优惠价的两倍;价格切换的细节见定价指南。钱主要花在输出上:第一轮账单里 98% 是输出 token。
| 项目 | 我们在 SandBase 的实际花费 | 同样 token 按 Google 优惠价 $2 / $10 |
|---|---|---|
| 第一轮回答 | $0.1507 | $0.0754 |
| 第二轮修复 | $0.1910 | $0.0955 |
| 一个场景加一轮修复 | $0.3417 | $0.1709 |
| 每月 100 个场景、各修一次 | 约 $34 | 约 $17 |
| 每月 1,000 个场景 | 约 $342 | 约 $171 |
月度估算假设每个场景都和我们这个差不多;如果像一些帖子那样一次输出 30k token,成本大约翻四倍。修复轮会把第一轮的完整回答当输入再发一次,这次 cached_tokens 为 0,全按原价计费。
本文所有 Argon 调用合计扣费 $0.3458,共 5 次有记录的调用(两次场景、两次算术探针、一次冒烟测试),另有一次同样很小的冒烟调用没记下 ID。
可复用的 Three.js 场景 prompt 模板
- 交付物和格式。 只要一个文件,不要解释,不要代码块;提取脚本仍然要能处理代码块。
- 依赖钉死。 importmap 写明版本和 CDN,而且这个 CDN 要在页面实际运行的网络里测过;禁止其他请求。
- 确定性。 用带种子的随机数,渲染结果可复现,bug 也能复现。
- 编号的场景要求。 每一条都能从截图或代码里核对:数量、灯光类型、贴图尺寸、转速。
- 相机边界。 距离上下限,加俯仰角上限。
- 测试钩子。 一个就绪标志,加一行 JSON 日志,给无头浏览器用。
- 自查指令。 成本很低,但这次没查出几何 bug,所以还是得渲染。
修复轮要逐条点名问题,写清你观察到了什么,而不只是你的猜测,并且明确“其他一律不改”。更多写法见 Argon 创意编程 prompt 指南。如果场景要加输入和游戏循环,可以看一句话做浏览器游戏那篇的单独测试。
常见问题
Gemini 4 Argon 能一次写出可用的 Three.js 场景吗?
我们这次第一轮就拿到了能加载、页面零报错的文件,15 条书面要求满足 14 条。望远镜这个看得见的部件错了,一轮修复后改好。合集里不少创作者也说要试两三次。
用 Argon 做一个 Three.js 场景大概多少钱?
按 SandBase 的 $4 / $20 标价,我们第一轮 $0.1507,加一轮修复共 $0.3417。我们这次输出 7,393 token;合集里创作者报的单次输出在 18k 到 28.5k token 之间,按每百万 $20 算,光输出就是 $0.36 到 $0.57。
生成场景时 Argon 用了 reasoning token 吗?
两次场景调用的 reasoning_tokens 都是 0。同一晚两个小算术探针分别报了 81 和 60,其中一个带了 reasoning_effort: "high",接口正常接受。场景调用没有设推理参数,SandBase 默认对应 Google 哪一档推理强度,我们不清楚。
SandBase 和 Google 直连价格一样吗?
不一样。SandBase 标价每百万 token $4 / $20。Google 直连到 2026 年 11 月 30 日是 $2 / $10,之后是 $4 / $20。
测试范围
测试范围说在前面:一个 prompt、一轮修复、一个场景,在 Mac 上的无头 Chrome 里用软件 WebGL 渲染。GPU 帧率、其他浏览器、Argon 重复生成同一场景的成功率,这里都没测。Lab 的统计是对一批精选 X 帖子做的关键词计数,创作者给出的数字都是他们自己的说法。更早的预览期报道写于正式开放之前,整个合集的分析见发布周数据研究。想自己跑同一个 prompt,Gemini 4 Argon 模型页有模型 ID 和当前价格。