【免费下载链接】LinearAbiltyCastingThreeJS
LinearAbilityCastingThreeJS 是一个基于 Three.js、Vite 与手写 GLSL 构建的技能特效(VFX)沙盒。其中 R 键触发的陨石技能(Cinder Fall)是理解该项目 Raymarched 火焰尾迹与熔岩裂纹着色器的最佳入口:一颗程序化生成的陨石拖着体积积分的火尾砸向目标,落地后撕裂地面、炸开一张持续发光的熔岩裂纹网络。本文带你完整拆解这套效果的实现思路。
🎯 陨石技能总览:一颗石头如何完成一次打击
陨石技能由五个阶段串联而成,每个阶段都对应一组独立的技术:
| 阶段 | 屏幕上发生了什么 | 背后的关键技术 |
|---|---|---|
| 投掷 | 石头离手,火花飞溅、屏幕闪光 | GPU 粒子 + 屏幕闪光(ScreenFlash) |
| 飞行 | 沿抛物线翻滚,表面熔岩缝隙越走越亮 | 程序化几何 + 热值 uniform 驱动 |
| 尾迹 | 身后约 7 米长的燃烧气体云 | Raymarched 体积火焰 |
| 爆炸 | 双层火球 + 冲击波环横扫地面 | SDF 爆发球(BurstSphere) |
| 余烬 | 碎片弹跳冷却,地面裂纹持续发光 | 闭式弹道 + 程序化裂缝网络 |
五个技能共享同一套基础设施(瞄准、池化、粒子引擎),所以读透陨石技能,基本就读通了整个沙盒的 VFX 管线。
🧊 先看效果:沙盒中的技能家族
冰霜长矛(Q)的截图:所有冰晶、冰雾都是程序化几何与 GPU 粒子,没有任何纹理贴图——这正是陨石技能同款的设计哲学。
风暴长矛(E)的截图:闪电束由一条相机朝向的 ribbon 条带在顶点着色器中摆出形状,陨石技能尾迹的"代理外壳"用的是同一个 RibbonGeometry 模块。
🪨 程序化陨石:一张纹理都没有的石头
陨石本体由 ProceduralGeometry.js 中的createAsteroidGeometry在 CPU 端实时雕刻:
- 基底:一个 icosphere,默认细分 3 层(1280 个三角形);
- 形变:低频噪声制造鼓包(
lumpiness)+ 高频噪声制造碎屑感(surfaceRoughness); - 切割:9 个平面像斧头一样劈出断口(
cuts/cutDepth); - 撞击坑:5 个凹碗冲压进表面(
craters)。
关键设计在 MeteorAbility.js 的_syncGeometry:这 9 个几何控制项会拼成一个"形状哈希",只有哈希变了才重建几何。因为一次细分 3 的陨石不过 1280 个三角形,直接重建比在顶点着色器里伪造轮廓更诚实——剪影、法线、投影全都真实可见。
陨石和它的碎片共用同一个InstancedMesh和同一套材质(1 个 draw call),碎片只靠 per-instance 的aSeed偏移裂缝噪声,保证没有两块碎片裂出相同的纹路。
🔥 熔岩缝隙着色器:裂缝是噪声的零交叉
岩体着色在 MeteorMaterial.js 中完成。它不替换MeshStandardMaterial,而是往标准 PBR 管线上"打补丁"注入自发光段——这样石头依然能投射/接收真实阴影、吃到 HDR 探针,岩石是实体的,而不是自发光贴片。
熔岩缝隙的核心只有一行思路:把 fbm 噪声的零交叉当作裂缝中心线。
float distance = min(abs(f1), abs(f2) / uCrackBranches); float fissure = 1.0 - smoothstep(width * 0.35, width, distance); // 张开的缝隙 float lip = 1.0 - smoothstep(width, width * 2.0, distance); // 两侧的焦黑带 float core = 1.0 - smoothstep(0.0, width * 0.45, distance); // 白热核心三层截面让裂缝读起来是"石头被撑开"而不是"画了一条亮线":缝隙处杀掉反照色、只露出下面的岩浆;焦黑带(lip)让裂缝"先有阴影、再有光";只有最中心的 core 才会烧到白色。
几个让效果成立的细节:
- 在 local space 采样:裂缝焊死在石头上、跟着翻滚;若用 world space(冰晶故意那么做以呈现"同一块石料"感),旋转中的陨石缝隙会滑动,瞬间穿帮。
uCharge加热曲线:uCharge从出手的 0 走到落点的 1,缝隙宽度width * (1 + uCharge * 0.8)——越接近目标裂缝越宽越亮,爆炸是"你看着它烧起来的"。- 迎风面受压热:法线与飞行方向的点积做幂衰减,朝前的面烧白、背风面保持黑暗,形成压缩发热的读数。
- 辉光软上限:
glow /= 1.0 + glow * 0.22,防止多条发光项叠加后把整块石头吹成白团。
💨 Raymarched 火焰尾迹:代理外壳 + 体积积分
火焰尾迹是整个项目最重的一块着色器,实现在 VolumetricFireMaterial.js。
核心思想:画出来的网格不是火焰,只是一个"代理外壳"(proxy hull)。那是一条相机朝向的 billboard 条带(RibbonGeometry的BILLBOARD模式),沿着飞行弧线展开;每个片段在片元着色器里从相机发出光线,对体积做发射 + 吸收积分。外壳唯一的职责是包住火焰——哪怕窄一像素,火焰就会被沿一条死直的边切掉,这是该技术唯一肉眼可见的失败方式,所以 JS 侧与 GLSL 侧共享同一个radiusProfile并刻意放大了 1.3 倍余量。
密度字段由粗到细分四层,顺序就是人眼读一团真火的顺序:
- 轮廓(silhouette)——围绕弧线的胶囊体,被单 octave 低频噪声调制出米级大小的叶瓣。没有这一层,堆再多高频湍流也只会把火焰边缘啃出小碎屑,整体仍是一根带阴影的管子;
- 涡卷(vortex roll-up)——热气体抛出的环形涡旋沿尾迹向下游迁移,通过旋转 (streamwise, vertical) 噪声域把场"折起来",产生卷曲、蘑菇状的云团。代码注释里写得很直白:普通 fbm 无论多少 octave 都只会做出云,做不出卷;
- 湍流(turbulence)——5 层渐进域扭曲的 value noise,octave 之间做旋转消除网格对齐、逐层加速上浮,让细结构撕成向上舔舐的火舌;
- 撕碎(shred)——侵蚀在轴心极弱、在边缘剧烈,火焰保住实心的燃烧核心,边缘溶解成丝缕与离散的烟缕。
着色不是调色板而是温度:每个采样点算出温度(K),用 Tanner Helland 的黑体近似blackbody(kelvin)取色,再按 Stefan–Boltzmann 律以(T / Tcore)^4.79放能——红边 → 橙身 → 白核的连续谱和巨大的内部动态范围都从物理里"掉"出来,而不是手工调色的。
还有两条血泪教训直接写进了代码注释:
- 温度只从最粗两个 octave读取。辐射功率随温度的高次幂放大,若用完整密度场驱动温度,噪声的嵌套闭合等高线会被放大成"玛瑙纹",火焰看起来像抛光玛瑙,任何调色都救不回来;
- 混合模式用 premultiplied "over" 而非加色——真实火焰既发射也遮挡。
性能上同样抠:包围体不是球而是火焰实际占位的椭球(多一个点积,换回成倍的采样密度);入口点做 dither 避免"洋葱圈";空区自适应粗步长、命中后回细步长;整个 march 用不透明场景的深度缓冲裁剪,火焰被地面和角色正确遮挡。
🌋 熔岩裂纹:撕裂地面的真实几何
落地的 GroundFissures.js 刻意不做 decal:它从撞击点长出 6 条蜿蜒的主裂缝,各自甩出闪电式侧支,沿裂缝唇缘还会掀起玄武岩块——裂缝有物理起伏,而不是一张发光的贴纸。
工程上的聪明之处:
- 单位圆盘烘焙:整张裂缝网络烘焙在半径 1 的圆盘里,顶点着色器乘
uRadius放大——fissureRadius因此是真正的实时滑块,拖一下就能缩放已经躺在地上的网络,无需重建; - 双 pass 渲染:每条 ribbon 画两遍——窄的白热 core + 宽幅加色 underglow,把橙红色的辉光"刷"到周围石面上;
- 奔跑的前沿:
openness = smoothstep(0, 0.08, uGrown - vDist)保证裂缝只在推进锋线后方张开,一道白色闪光骑在锋线上,裂纹看起来是自己"撕"开的。
裂纹默认fissureLife: 6.5秒,在坑烧完之前一直脉动发光(settings.js)。
⏸️ 暂停也能调参:"只掷骰子"法则
这个沙盒最反直觉的能力:按P暂停后,所有 938 个滑块依然生效。陨石技能遵循的规矩是——一次 cast 只捕获骰子,不捕获尺寸:一个种子、一个翻滚轴、每块碎片几个无量纲随机数(角度、仰角、速度抖动)。不记录一米、一弧度、一秒。
轨迹、岩石大小、缝隙宽度、碎片抛射全部在 update 循环里对着settings.meteor逐帧解析。碎片飞行更是闭式弹道(位置是落地后时间的解析函数)而非逐帧积分——所以拖arc会重新扬起已经在空中的火焰,拖chunkSpeed会重抛已经落地的碎片。尾迹的中心线同样是从_arcPoint实时采样派生的,而不是记录历史帧。这就是"Raymarched 尾迹可以被编辑"的全部秘密。
🚀 快速上手:三步跑起陨石技能
git clone https://gitcode.com/gh_mirrors/li/LinearAbiltyCastingThreeJS cd LinearAbiltyCastingThreeJS && npm install && npm run dev打开 Vite 打印的地址后:R蓄力陨石,左键沿箭头方向投掷;G打开 VFX 编辑器,P暂停后继续拖arc、trailSpan、fissureRadius等参数看效果实时变形。陨石技能约 150 个参数的完整清单见 settings.js 的meteor块。
📁 核心文件索引
| 文件 | 职责 |
|---|---|
| MeteorAbility.js | 技能状态机:弧线求值、碎片弹道、尾迹外壳重建 |
| MeteorMaterial.js | 熔岩缝隙零交叉着色器、charge 加热、迎风面受压热 |
| VolumetricFireMaterial.js | Raymarched 黑体体积火焰(四层密度场) |
| GroundFissures.js | 地面熔岩裂纹网络 + 玄武岩唇缘 |
| ProceduralGeometry.js | 程序化陨石/碎片几何雕刻 |
| RibbonGeometry.js | 相机朝向条带:尾迹外壳、瞄准环共享 |
| settings.js | meteor参数块——所有实时滑块的唯一来源 |
| README.md | 项目总览、控制键位与架构说明 |
【免费下载链接】LinearAbiltyCastingThreeJS
相关推荐
如何用MonoGame创建逼真火焰粒子效果:GPU模拟与着色器实现完整指南
如何用MonoGame创建逼真火焰粒子效果:GPU模拟与着色器实现完整指南 MonoGame是一款强大的跨平台游戏开发框架,支持开发者创建高性能的2D和3D游戏
游戏开发图形学深度学习赋能实时火焰检测:技术解析与实战指南
深度学习赋能实时火焰检测:技术解析与实战指南 你知道吗?当火灾发生时,每一秒都至关重要。基于深度学习的实时火焰检测技术,正以其惊人的速度和准确性,为安全防护带来
Nitro与静态站点生成器集成:构建极速网站的完整指南
Nitro与静态站点生成器集成:构建极速网站的完整指南 Nitro是一款强大的通用Web服务器引擎,专门为构建现代Web应用程序而设计。作为Nuxt框架的核心引
后端Web框架SSR
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考