智能体交来一座 89 万面的祈年殿:3D 场景验收,我靠 9 张截图和一份报告
引语:智能体说"做完了"的那一刻,这句话本身最不值钱。3D 渲染是黑盒输出——代码不报错,画面照样可以全黑。我把一次真实的 WebGL 工程验收拆开讲:天坛祈年殿夜景复刻,89 万三角面,9 张命名截图加一份 PASS 报告,方法改改就能用。
1. 起点:不敢直接信的"做完了"
11 月 3 日我用 Hermes Agent 跑了一单天坛祈年殿夜景复刻:GLB 实测模型 894,634 个三角面、110 个网格、通高 38.1 米、台基半径 33.4 米;three.js 全家桶本地 vendor 化(主库 1.3MB,控制器、加载器、后处理、着色器各自成目录),最终收敛成单文件 index.html,818 行。模型文件 12.8MB,整个工程 22MB,断网可跑。
这类工程最麻烦的地方不在建模,在验收。普通页面坏了会报错,3D 渲染不会:材质路径写错,模型整块消失;天空渐变系数错了,画面从"深夜"变"阴天";曝光曲线崩了,夜景灰成一片。这些全都不进控制台、不触发异常。智能体跑完汇报"渲染正常",你盯着画面只能说出"感觉不太对"——感觉没法进回归流程。
所以动工前我先定了规矩:这一单的完成态不是"画出来了",是一份能落盘的报告。
2. 第一道关:环境先关死
验收报告里最先看两个数:ext_requests 等于 0,js_errors 等于 0。
前者管依赖。3D 工程最容易留暗依赖:渲染库从 CDN 拉、字体从海外 CDN 引、模型从某个测试地址读。开发时一切正常,交付后对方内网一断,白屏。这次把 vendor 目录整个落盘再验收,跑一轮网络请求计数,归零才算环境干净。
后者管低级错误。控制台一条红字都没有,才有资格谈画面。
3. 第二道关:把"好看"翻译成数
夜景画面最怕两种死法:全黑(模型没加载出来)和全亮(曝光崩了)。肉眼判断"偏暗"没有复用价值,我把画面拆成三个可数的量。
第一个是天空底色。在画面上部取一条采样带,跑中位数而不是平均值——单颗星、一朵烟花都会污染均值,中位数稳。报告里 sky 是 R=53、B=113:深蓝底、蓝远大于红,深夜天空就该是这个比例。后来我换采样带独立复测,得 R=71、B=134——数值有出入,量级和比例一致。像素判据要定成区间和比例,别定死值,换个窗口尺寸就误报。
第二个是亮度覆盖。把画面划成采样网格,逐格算亮度,数超过夜阈值的格子。报告口径 bright 49/77:约三分之二的位置有内容在发光——楼体轮廓、檐角灯带、地灯,符合"夜景有主体"的预期。这个数掉到个位数,多半是模型没渲染;冲到满分,是曝光或雾参数错了。
第三个是尺寸标定。terraceR 33.4、hallTop 38.1 两个米级数进报告,配合机位高度取 0.84 倍通高的视点参数。尺寸数据防的是"凭感觉像"——建筑比例错了,画面再美也是错的。
采样逻辑不长,探针十几行,可以直接抄:
# 像素探针:天空蓝通道中位数 + 亮度覆盖格数(夜景判空/判曝)
from PIL import Image
im = Image.open("verify.png").convert("RGB")
w, h = im.size; px = im.load()
sky = sorted(px[x, y][2] for y in range(int(h*.08), int(h*.18), 4)
for x in range(int(w*.30), int(w*.70), 6))
bright = 0
for gy in range(7):
for gx in range(5):
r, g, b = px[int(w*(gx+.5)/5), int(h*(gy+.5)/7)]
bright += 0.299*r + 0.587*g + 0.114*b > 28
print("sky_b_median=", sky[len(sky)//2], "bright_cells=", bright, "/35")
4. 性能降级写进策略
报告里有一对组合:fps 11.1,pixelScale 0.8。89 万面加泛光、环境光遮蔽这条后处理链,中端设备跑不满 60 帧,智能体的处理是降采样渲染再上屏,把帧率稳在可交互区间。这个决策值得单独记录:性能不达标时第一反应是降 pixelScale,画质损失线性可控;砍后处理是断崖,泛光一关,夜景直接变白模。
5. 截图命名即用例
9 张验收截图全部带语义命名:成图、深夜檐角、vendor、evidence、adhoc、烟花-主文案、烟花-署名、烟花-高度调整、烟花-循环与镜像。文件名就是用例名,看目录就知道验过什么。
时间线更说明问题:14:52 出第一张成图和深夜檐角,15:07 全项 PASS 落盘;此后烟花功能迭代四轮——15:57 署名、16:00 主文案、16:50 高度调整、17:04 循环与镜像,每轮动代码就补一张对应命名的截图。验收资产从"一次性门禁"变成了"回归测试带"。这正是语义命名的原因:名字带不进回归,截图就只是一堆过期图片。
最后落盘一份 verify-report.json:环境两项、像素三项、性能两项、机位参数、结论 PASS、issues 空数组。八百行代码的交付物,验收摘要一屏读完。
6. 可以直接抄的验收提示词
下一次 3D 工程给智能体的指令,改改就能用:
[3D 场景验收员]
工程完成后不要只汇报"渲染正常",按八步产出验收包:
1. 依赖审计:统计页面外链请求数,要求归零;vendor 目录清单化核对。
2. 控制台清零:js_errors 必须为 0,有红字先修再验。
3. 像素采样:天空区取中位数 RGB,夜景核对蓝通道大于红通道、量级在深夜区间。
4. 亮度覆盖:网格采样数超阈亮格,夜景落在四到七成之间;过低判模型未渲染,过高判曝光失控。
5. 尺寸标定:关键尺寸(米)与机位参数写入报告,防"凭感觉像"。
6. 性能策略:fps 低于阈值时优先降 pixelScale,记录取值与理由。
7. 截图语义命名:每张 verify 截图文件名即用例名;功能每改一轮,补一张对应截图。
8. 报告落盘:指标汇总成 verify-report.json,结论 PASS/FAIL 加 issues 列表,缺任何一项视为未完成。
7. 总结
三句话收尾。渲染代码是写给 GPU 的,验收代码是写给"不信"的——智能体时代你保留的最后一道岗,就是替它设计"怎么证明做对了"。数字判据定区间和比例,别定死值,否则换个窗口就误报。验收截图的文件名是用例名,带不进回归的名字只是过期图片。
那晚看烟花在祈年殿檐角炸开时,我信它画对了——因为 9 张截图和那份 PASS 报告,都替我把过关。
作者:林华鼎 · 华为云开发者发展与支持部 · 科技博主系列
- 点赞
- 收藏
- 关注作者
评论(0)