✦设计雷达
知识地图
2026-09-27 · 今日最炫

WebGPU Gommage

Clair Obscur 式消解:MSDF 字被 TSL 噪声咬碎,尘埃与花瓣粒子同步爆发。

WebGPU Gommage 截图 打开网站 ↗
大白话拆解

它是什么:一行字像被风化一样碎掉、化成尘埃和花瓣飘走,灵感来自游戏《光与影:33号远征队》。

好在哪:“消散”这个瞬间做得很有仪式感:字不是淡出,而是从边缘一点点被“啃”掉,同时粒子喷出来。

怎么做到的:

  1. 用噪声图决定每个笔画先碎哪里,数值一过阈值那一块就消失。
  2. 碎掉的位置同步发射成百上千的尘埃和花瓣(同一个模型批量复制,所以不卡)。
  3. 只给发光的部分加泛光,画面亮而不糊。
完整技术拆解

今日拆解 · WebGPU Gommage

为何选它

8 条里它把《Clair Obscur: Expedition 33》里的「Gommage」消解瞬间搬到浏览器:MSDF 文字被噪声驱动的 TSL 着色器咬碎,同步喷出尘埃与旋转花瓣粒子,再用 MRT 选择性 bloom 收尾。WebGPU + TSL + InstancedMesh 一条管线讲完,比漂亮落地页更值得拆。

实际在源码里找到的技术栈

Three.js r181(WebGPU 路径)bundle:const em="181" / window.__THREE__=em;REVISION:em;WebGPURenderer 出现多次;await this.#threejs.init()
TSL / NodeMaterialFn( ×56;nodeMaterial 相关 ×71;文章与 demo 标题写明 *Three.js & TSL*
InstancedMesh 粒子InstancedMesh ×28;文章步骤:dust + petal 均用 InstancedMesh
MSDF 文字MSDFText ×6;依赖 three-msdf-text-utils(package.json 写 ^1.2.1;bundle 内未找到字面量 1.2.1 → 精确补丁版以仓库为准)
GSAP 3.14.2vo.version="3.14.2";gsapVersions push
Vite 构建package.json:vite ^7.3.1;资源 hash 文件名。生产 bundle 无 vite 字符串
tweakpane(开发调试)package.json:^4.0.5;生产 bundle 未找到 tweakpane → 推测仅本地调试用
未使用 / 未证实未找到 React / R3F、Howler、WebGLRenderer 作为主路径(bundle 含 WebGLRenderer 符号但是 Three 全集;主路径文章与代码均走 WebGPURenderer)

package.json 还写明:three: ^0.181.0,与 window.__THREE__="181" 一致。

核心效果怎么工作(源码 + 标明推测)

1. WebGPU 场景启动(确认)

文章摘录:new THREE.WebGPURenderer({ antialias: true }); await this.#threejs.init();,tone mapping 用 ACESFilmicToneMapping。

2. MSDF 文字溶解(确认 + 推测)

用 three-msdf-text-utils 生成 MSDF mesh;片断/TSL 里用 noise(bundle 中 noise ×65)驱动 dissolve 阈值。推测:阈值之上的 texel 透明度归零,同时把同一噪声场喂给粒子发射,保证文字与粒子「同一刀」切开。

3. 尘埃 + 花瓣 InstancedMesh(确认)

文章目录步骤:

  1. Create a noise-driven dissolve effect
  2. Spawn and animate dust particles with InstancedMesh
  3. Spawn petal particles with bend + spin
  4. Add selective bloom with MRT nodes

花瓣用 GLB 模型(文章提到 public/models/petal.glb)。

4. 选择性 Bloom / MRT(确认)

文章写明 *selective bloom using MRT*;bundle 内 mrt ×20、bloom ×5。

5. 伪代码(忠实于教程结构)

boot:
  renderer = new WebGPURenderer({ antialias: true })
  await renderer.init()
  renderer.toneMapping = ACESFilmicToneMapping
  text = MSDFText(fontAtlas, "GOMMAGE…")   # three-msdf-text-utils
  dust  = new InstancedMesh(dustGeo, dustNodeMat, N)
  petals = new InstancedMesh(petalGeo, petalNodeMat, M)  # petal.glb

each frame / on trigger (GSAP 3.14.2 timeline):
  progress = gsapProgress  # 0→1
  textMat.dissolve = progress          # TSL Fn + noise
  emit dust/petals where noise crossed
  petal instances: bend + spin
  post = mrt bloom (selective)
  renderer.render(scene, camera)

如果我来重做(步骤清单)

  1. Vite + three@0.181.0,主路径只用 WebGPURenderer + TSL(无适配器时给降级提示)。
  2. 用 msdf-bmfont 生成字体图集;three-msdf-text-utils 出字。
  3. 写 TSL Fn:Perlin/噪声采样 → dissolve mask。
  4. 两个 InstancedMesh:dust(小四边形)+ petal(GLB);用同一 progress 驱动发射与自旋。
  5. MRT 选择性 bloom,只让亮粒子/边缘进光晕。
  6. GSAP timeline 串起「静置 → 消解 → 粒子爆发 → 收束」。

一句话

WebGPU Gommage 用 Three r181 + TSL 把 MSDF 字咬碎成尘埃与花瓣,是今天技术浓度最高的一刀。

小白课

零基础也能看懂。先认识这件作品用到的技术,再学一个知识点。

1技术栈小白版

只列拆解里在源码中确认过的技术。点开看它在这件作品里做了什么。

Three.js r181(WebGPU 渲染器)3D 网页界最常用的「全能工具箱」:场景、相机、灯光、材质都是现成的零件,拿来就能搭。

在这件作品里用它新一代的 WebGPURenderer,把文字、尘埃和花瓣画出来。

怎么认出来从画面上看不出品牌,但很多 3D 网页都用它。在浏览器开发者工具的控制台输入 __THREE__,能看到版本号(这里是 "181")。

TSL / 节点材质用「搭积木」的方式写着色器:一块块节点拼起来,就得到一个效果。

在这件作品里写出「文字被一张噪声图一点点咬掉」的溶解效果。

怎么认出来写法看不出来;但看到溶解、烧穿、流动花纹这类效果时,背后通常就是着色器。

InstancedMesh(实例化)像盖印章:同一个图案一次盖几千下,每一下的位置、大小、角度都可以不同。

在这件作品里成百上千的尘埃和花瓣,都是同一个形状被「盖章」复制出来的,所以数量很多也不卡。

怎么认出来画面里有大量长得一样、只是位置和角度不同的小东西(花瓣、树叶、星星)。

MSDF 文字一种「放大不糊」的字体存法:把每个字的边缘信息存进一张小图里,需要多大就现场画多大。

在这件作品里标题文字用 MSDF 画在 3D 场景里,所以任何大小都很锐利,而且能被着色器从边缘开始溶解。

怎么认出来3D 场景里的文字放大、旋转后,边缘依然干净清晰。

GSAP 3.14.2动画的「导演分镜表」:谁什么时候出场、动多快、怎么加速减速,全写在一条时间轴上。

在这件作品里用一条时间轴把「静止 → 消解 → 粒子爆发 → 收束」这几幕串起来。

怎么认出来网页动画很流畅,节奏讲究,多个东西有先有后地依次出场。

MRT 选择性 Bloom只给「该发光的东西」开柔光滤镜,而不是整张照片都糊上一层。

在这件作品里只让亮的粒子和溶解的边缘发光,文字本身依然清楚。

怎么认出来画面里只有部分元素带光晕,其他地方依然锐利。

2今日知识点

3D 与实时图形 · 第 12 课

粒子系统:成千上万个小东西

烟、火、雪、灰尘、火花、一群萤火虫……这些东西没有固定的形状,很难用「一个模型」做出来。办法是:用成百上千个很小的点(粒子),每个都按一套简单的规则动,合在一起就像烟、像火。这就是粒子系统。

一个粒子系统,通常只做三件事:

  • 发射:从哪儿冒出来、每秒冒多少个;
  • 更新:每一帧怎么动(速度、重力、风、旋转、慢慢变淡);
  • 消亡:寿命到了就消失,或者回收再用。

在 Gommage 里:文字哪一块被「咬掉」,哪一块就发射出尘埃和花瓣;它们飘起来、转起来、慢慢变淡,最后消失。溶解和粒子用的是同一张噪声图,所以看起来就像字真的碎成了灰。

这么多粒子为什么不卡?因为用了 InstancedMesh(像盖章):GPU 一次就能画出几千个相同的形状,只是每个的位置不一样。

一句话记住:粒子系统 = 很多个小东西 + 简单的规则 + 有生有灭。

它从哪里来

「粒子系统」这个说法来自 1983 年 William Reeves 发表的一篇论文。他当时在卢卡斯影业(Lucasfilm)的电脑部门,为电影《星际迷航 2:可汗之怒》(1982)做了「创世纪」片段——一整颗星球被火焰席卷——用的就是这个方法。

从那以后,电影特效和游戏里的火、烟、魔法、爆炸,几乎都沿用了粒子系统的思路。

经典参考

  • 《星际迷航 2:可汗之怒》(1982)「创世纪」片段粒子系统最早的经典,网上搜「Genesis effect」就能看到。
  • William Reeves《Particle Systems — A Technique for Modeling a Class of Fuzzy Objects》(1983)提出这个概念的论文。标题里的 fuzzy objects,就是「模糊、没有固定形状的东西」。
  • Codrops 上的 Gommage 教程就是今天这件作品的作者写的,一步步讲怎么做尘埃和花瓣粒子。
怎么看 / 怎么练 · 约 8 分钟
  1. 打开 Gommage,看 3 遍消解:第一遍只看粒子「从哪儿冒出来」;第二遍只看它们「怎么动」(往上飘?会转吗?);第三遍只看它们「怎么消失」(变小?变淡?)。
  2. 在纸上画三个格子:发射 → 更新 → 消亡,每格写一个你看到的细节。
  3. 在生活里找一个「粒子系统」:烧开水冒的蒸汽、路灯下的雨丝、阳光里飘的灰尘。用同样的三个格子描述它。

小词典

粒子(particle)
粒子系统里的一个小单位,通常只是一个点、一个小方片或一个小模型。
发射器(emitter)
粒子冒出来的地方,决定从哪儿发、发多少、朝哪个方向。
寿命(lifetime)
一个粒子从出现到消失的时间。
实例化(instancing)
让 GPU 一次画出很多个相同形状的技巧,像盖章。
噪声(noise)
一种「有规律的随机」图案,看起来像云或大理石纹,常用来让效果显得自然。

3知识地图进度

3D 与实时图形第 12 课 / 共 16 课
这条线已学 2 课全部已学 10 / 89
下一课建议3D 第 2 课 · 坐标与空间:x、y、z 和相机 打开知识地图 ›
当天另外 7 个
网站
Cerebrium
Serverless GPU 基建站:冷启动与模型部署用干净产品视觉讲清楚。
小游戏
Cosmos Museum
宇宙美术馆:Three.js bloom + 透镜光晕,在静默星光里跳世界。
小游戏
Custom Shaped Cursor Trail
可插拔笔刷函数的光标拖尾:Three.js WebGPU + TSL 把指针变成材质笔。
网站
Provider Studio
精品酒店的品牌与气味设计:克制排版把「视觉 + 气味」卖成感官系统。
App UI
Statements
PDF 银行流水一键转 CSV:无注册工具页,信息层级干净得像财务产品。
网站
The Tie Break
New Balance × Miu Miu × Coco Gauff 互动站:把时尚联名做成可玩的抢七叙事。
App UI
Typewave
Figma 字阶插件落地页:一键生成字体比例、样式与可导出 CSS。

设计雷达 · 每天 8 个值得看的网站、App UI 和网页小游戏