[Godot] CPU Particles 3D 制作面片刀光特效

1,195 阅读7分钟

1.基础

1.1 教程

Unity Shader Graph - Slash Shader Effect Tutorial

1.2 创建面片

按 shift+A 新建一个圆柱体,不用封顶

图片.png

图片.png

按 tab 进入编辑模式,按 ctrl+R 点击母线,对母线环切奇数道

图片.png

按 shift+alt 选择除了中间一圈之外的顶点或边或面,按 s 缩放

图片.png

按按 shift+alt 选择除了中间三圈之外的顶点或边或面,按 s 缩放

图片.png

最后一次缩放同理

好的,我发现这样做是错的

最后看上去也很难调

图片.png

然后从俯视来看 UV 的分布也没有最好

图片.png

给我的感觉就是,如果想要兼顾好看的弧形和大小相对均匀的 UV 就会有点艰难

个人感觉正确的思路应该是先摆好 UV 大小

图片.png

然后再对一圈边按 s 再按 z 在 z 方向上缩小

图片.png

这样最终的就可以兼顾形状和 UV

图片.png

当然我这可能也是强迫症了吧

1.3 平滑着色 自动光滑

在物体模式下右键物体选择平滑着色,这使得游戏引擎的渲染管线在计算物体的三角面上的颜色时对三角形的三个顶点取插值

平直着色自然就是不插值

对比:

图片.png

法向的自动光滑也可以选上

图片.png

这样,两个面的法向的夹角如果小于给定值,就会对两个面之间的法向作平滑处理

这样说是很难体会到具体效果

可以在 blender 中使用快照材质来快速地预览

图片.png

关闭自动光滑

图片.png

开启自动光滑 30度

图片.png

1.4 导入到 Godot

在 Blender 中导出为 glTF2,为了防止导入到 Godot 时发生错误,导出设置取消勾选动画和蒙皮

直接把得到的 glb 文件拖到 Godot 就可以导入了

打开这个 glb,在视窗中选择 mesh,勾选 save to file,新建一个 mesh 资源,最后选择视窗底部的重新导入,也就是保存,这样就可以在其他地方引用这个 mesh 了

图片.png

1.5 创建粒子系统

本来想用 GPU Particles 3D 的,因为 GPU 的性能更好一点嘛

但是一搞才发现 GPU 的能够设置的参数太少了……而且根本没有地方设置重力和速度方向

这可能是他自己的一些逻辑吧,但是对于我们要求的发射一个静止的粒子来说肯定是不行的

所以使用了 CPU Particles 3D

初始时只需要改生命周期,速度方向,重力就好了

要改速度大小才改 speed scale,但是调成 0 速度却不能把 speed scale 调成 0,而是应该把是速度方向调成 0

图片.png

在测试的时候应该把 one shot 设置为 false,这样粒子就不会消失,就比较好看 shader 的效果

1.6 创建贴图(其实没必要)

水平拉一条从黑到白的渐变

图片.png

取中间的一小条就行了

图片.png

最后导出为 png

BlackToWhiteGradient.png

还需要一个遮罩

从左下角到右上角拉一个渐变

图片.png

缩放选区

图片.png

羽化选区

图片.png

反向选择并删除

图片.png

然后再加上一个黑色底

有一个问题是,渐变工具不能选择从前景色到透明,而是应该选择从前景色到背景色

从前景色到透明:

question.png

从前景色到背景色:

截图 2022-09-10 21-48-14.png

区别在于透明的像素会被不透明的像素覆盖,所以作为背景的图层反而压过了上层图层

贴图导入 godot 的时候要在 import 栏吧模式改为无损 lossess

图片.png

不然就会出现这种脏脏的条纹

截图 2022-09-12 00-41-47.png

教程里是这么制作贴图的,但是其实 godot 的 shader 里面有现成的 GradientTexture

所以其实没有必要制作这样的贴图hhh

而且我发现一个奇怪的点在于,对自己的 gradient png,即使是选了 lossess,取 0 次幂的时候还是会出现明显的黑条

图片.png

我是不太能理解为什么一个数取 0 次方不是 1……可能还是跟图片这方面的设置有关吧

总之用内置的 GradientTexture 就没有这些毛病

1.7 制作 shader

单独连一个 vertex 到输出的效果:

截图 2022-09-08 23-20-27.png

截图 2022-09-08 23-13-30.png

红色是 (1,0,0),绿色是 (0,1,0) 黄色是 (1,1,0)

感觉跟教程中的不一样

后面想想,他那个 unity 中的 vertex color 在 godot 中应该是 color 才对

还有他 unity 里面的 Voronoi 在 godot 的 NoiseTexture 里没有

但是用 Voronoi 做出来一个洞一个洞的实在是有点不太符合审美,还不如简单的噪声

综上,照抄教程的 shader 如图所示

图片.png

基本的原理其实就是使用一个 gradient 控制 mask,其中 gradient 加一个 pow 就可以控制黑与白的渐进分界线的大概位置,进而控制整个特效“溶解”的位置

他为什么要给 mask 也乘一个渐变的目的只是为了给“溶解”一个造型而已

综上,最简的 shader 如图所示

图片.png

1.8 制作动画

直接使用 AnimationPlayer 对 shader 中 pow 的参数设置两个关键帧就好了

particle 的 oneshot 应该是不用打开的,控制 visible 就好了

如果播放 anim 没有反应的话

图片.png

如果设置好了关键帧但是播放没有效果的话,可以到 AnimationPlayer 的 监视器 中把 CurrentAnimation 换成你新建好的动画,然后再播放试试

图片.png

最后效果图大概是这样……还有很多可以调的

图片.png

2.改进

2.1 面片形状

把面片由原来的圆盘改成扇形

我一开始使用的是先选择一个面,再按 A,使用 光照拼图展开 这种方式

图片.png

结果在游戏中显示得很丑,感觉可能是 UV 顺序不对导致的接缝不对?

图片.png

如果先普通的 UV 展开,然后再先选一个面,再按 A,使用 按活动四边面展开

那么得到的是一个梯形

图片.png

图片.png

因此首先要把一个面变成规整的长方形,然后才能 按活动四边面展开

图片.png

图片.png

为了方便拉伸,勾选 约束到画布边缘

图片.png

单独选择一个面的所有 uv 岛,先拉满全屏,然后 x 上缩放 0.5

图片.png

图片.png

最后拼起来就好了

图片.png

效果如图

图片.png

搞来搞去感觉很麻烦

其实单独一个面片也可以啦,禁用背面剔除就好了

图片.png

之后看了教程才知道要先按光照贴图展开,然后再先选一个面再全选再按活动西边面展开

图片.png

图片.png

然后再使用拼排孤岛,就可以让这些孤岛完美地充满一边

最后再选择一侧的所有边,约束到画布边缘之后直接拉伸到画布边缘

图片.png

woc,好像好看了许多

图片.png

看来我使用那种 3d 圆环形状是个错误的决定

2.2 uv 排列

同时这个 uv 排列的方式也要注意

这样子排,x 方向是径向

图片.png

y 方向是径向

图片.png

但是 shader 中 gradient 是 x 方向的,也就是沿着 uv 的 x 方向渐隐,所以 y 方向是径向才是对的

2.3 shader v2

然后我现在知道那个 mask 为什么要黑边了,黑边可以隐藏边缘,看上去形状没那么死

最后 shader 还是改成这样了……

我给 mask 乘了一个系数,让他看上去不要太透明

图片.png

最终效果

output.gif

2.shader v3

之后又注意到运算的两个参数是分先后的……

所以说 pow 的 a 是底,b 是幂。那么对于 color 来说 pow 得到的应该越来越白,mask 得到的应该越来越黑,所以 color 之前连接的 pow 的两个参数反接,mask 之前链接的 pow 的两个参数正接

图片.png