本系列教程的代码将开源到该仓库,前几篇文章的代码也会陆续补上,欢迎大家 Star:github.com/DesertsX/th…
本系列的代码同时放到了 Codepen Collection,欢迎学习:codepen.io/collection/…
此外,之前和之后的所有文章的例子都将更新到这里,方便大家和古柳一起见证本系列内容的不断壮大与完善过程 www.canva.com/design/DAF3…
继续放新加上的群友的赞扬!看到群友把前面七篇全认真看了并每篇都点赞,甚至发现了此前没人发现的 bug,值得表扬👍!
正文
在前两篇关于顶点着色器的文章里,古柳教大家应用 sin、random、noise 等函数来移动顶点、改变几何体形状,并介绍了将 noise 数值作为颜色的一些方法。
本文古柳将教大家如何对顶点进行旋转,不过因为球体的顶点怎么旋转球体形状都不变,所以我们用长方体讲解更直观。通过对顶点旋转不同角度可以实现类似“扭麻花”的效果。
长方体
下面是简单的一些设置,我们使用 BoxGeometry
并且在 shader 里用 vUv 作为颜色,相机在 z=3 的位置看向场景中心、正对长方体。
1 | js复制代码const camera = new THREE.PerspectiveCamera(75, 1, 0.01, 100); |
当长宽高都为1时,可以看到立方体每个面都有各自的 (0,0)-(1,1) uv 值,看着像由6个 plane 组成。不同几何体的 uv 效果会很不一样,这点大家替换几何体看看就会发现,不过数值范围都是0-1不会变化。
将长度设为3,方便后续沿x轴扭麻花。这里可以看到长度拉长后,uv 青红颜色效果也只是相应的拉长,4个角的颜色不变,背后数值范围也是不变的。
之前讲解片元着色器时选用 1:1 的 plane 作为例子是为了不使大家对 uv 产生困惑,实际上不论是这里的 3:1,还是任何比例,uv 各自都是0-1的范围,只是图形不是 1:1 时咋看起来会有些奇怪。
条纹效果
知道长方体上 uv 的效果后,我们可以将 vUv.y 乘以3.0再通过 fract 取小数然后对0.5取 step 从而使得数值在0/1/0/1/0/1之间变化,最后用该数值来 mix 插值两种颜色从而实现重复条纹效果。
这里的红色是 #d8345f
,可以通过该链接将16进制格式直接转化成 GLSL 里的 rgb 数值,即 vec3(0.847, 0.204, 0.373)
。链接不用记也没事,要用时直接谷歌 glsl hex to rgb
即可。
1 | C#复制代码varying vec2 vUv; |
如果大家是跟着本系列教程一篇篇学下来的,相信这里红白条纹的实现闭着眼睛也能写出来了吧。如果有不理解的地方,可以看前面文章复习下:「手把手带你入门 Three.js Shader 系列(二) - 牛衣古柳 - 20230716」。
旋转顶点
完成上述准备工作后,我们就可以开始对顶点进行旋转。谷歌搜索 glsl rotate
后从这个链接拷贝 glsl-rotation-3d
部分的函数到顶点着色器里。rotate() 函数接收待旋转的三维点坐标、旋绕的轴、旋转角度这三个参数,返回旋转后点的坐标位置。
1 | C#复制代码// glsl-rotation-3d |
长方体沿x轴拉长,那么就让顶点 position 都绕x轴旋转,即 axis 用 (1.0, 0.0, 0.0) 表示;旋转角度用弧度值表示,需要用到 PI 值,可以通过 const float PI
声明和赋值。先让所有顶点统一绕x轴旋转 PI/4.0 即45度,看起来已经成功生效。
1 | C#复制代码uniform float uTime; |
让角度随时间变化,就能实现 mesh.rotation.y=time 同样的效果。
1 | C#复制代码// float angle = PI / 4.0; |
改变 axis 就能绕其他轴旋转。
1 | C#复制代码// vec3 axis = vec3(1.0, 0.0, 0.0); |
旋转角度随x值而变化
当然这里还是绕x轴旋转所以 axis 不用变。为了实现前文所说的沿x轴扭麻花的效果,我们需要使旋转的角度随顶点坐标里的x值而变化,而不是所有顶点都用统一的数值。此时会发现长方体形状变得挺别扭、挺奇怪,中间区域过渡地不够丝滑。
1 | C#复制代码float angle = position.x; |
原因想来大家也能猜到,就是长方体的细分数不够、顶点不够多,中间没有顶点、没有操作的空间,只有两端才能旋转,所以扭转得很生硬。通过设置 material 的 wireframe:true 就能应证我们的想法。
1 | js复制代码const geometry = new THREE.BoxGeometry(3, 1, 1); |
增加长方体的细分数
我们以2、4、8、16、32、64……等2的倍数来增加长方体的细分数,会发现差不多在32以后中间扭转过渡就很丝滑了。毕竟图中长方体就这么点长度,切成32份已经很细了。这里采用64也没什么特别的缘故,反正 shader 里都是同样轻松拿捏,用大些的数值也无妨。
1 | js复制代码// const geometry = new THREE.BoxGeometry(3, 1, 1); |
随着细分数增加、顶点数增多,中间顶点随着x坐标的变化以不同角度发生旋转,从而有了丝滑的扭曲效果。当我们把 position.x + uTime
作为 angle 时就能使扭转效果随之动起来。
1 | C#复制代码// ... |
其他变体
除此之外我们还可以随意在 angle 加些内容来实现不同的扭曲动画效果,大家可自由发挥,没准会有意外之喜。
1 | C#复制代码float angle = position.x + sin(uTime) * 3.0 + uTime; |
1 | C#复制代码float angle = position.x * sin(uTime) - uTime; |
Kinetic Typography
以上就是“扭麻花”效果的全部内容,并不复杂、并不难懂。
古柳之所以想讲这个效果,一方面是因为想教大家顶点旋转,一方面是想到这个 Kinetic Typography
动态文字排版/文字动效的实际例子(也这是上面 #d8345f
红色的出处,并非凭空冒出来的)。
扭转长方体后再结合文字会使人眼前一亮,后续讲解到 shader 里的纹理贴图、纹理采样时,古柳会再带大家把结合文字部分补上,敬请期待!
其他文字效果同样不错,有机会古柳会在教程里多讲些例子。
暂时舍弃的 WebGL Blob
其实一开始古柳设想的讲解顶点旋转的例子是下面这个效果,即在 noise 值偏移顶点后,加上旋转顶点,再加上 Cosine Palette
(另一种 shader 里的配色方法),从而实现出这种酷炫的 WebGL Blob 效果。不过一些细节古柳觉得解释不好,远不如长方体“扭麻花”直观好懂,故而进行了取舍。当然其中的 Cosine Palette
古柳后续还是会教大家的。
小结
本文的内容比较简单,没啥好总结的。最后照旧是本文的所有例子合集,大家要好好复习哈。
相关阅读
「手把手带你入门 Three.js Shader 系列」目录如下:
- 「断更19个月,携 Three.js Shader 归来!(上) - 牛衣古柳 - 20230416」
- 「断更19个月,携 Three.js Shader 归来!(下) - 牛衣古柳 - 20230421」
- 「手把手带你入门 Three.js Shader 系列(七) - 牛衣古柳 - 20230206」
- 「手把手带你入门 Three.js Shader 系列(六) - 牛衣古柳 - 20231220」
- 「手把手带你入门 Three.js Shader 系列(五) - 牛衣古柳 - 20231126」
- 「手把手带你入门 Three.js Shader 系列(四) - 牛衣古柳 - 20231121」
- 「手把手带你入门 Three.js Shader 系列(三) - 牛衣古柳 - 20230725」
- 「手把手带你入门 Three.js Shader 系列(二) - 牛衣古柳 - 20230716」
- 「手把手带你入门 Three.js Shader 系列(一) - 牛衣古柳 - 20230515」
照例
如果你喜欢本文内容,欢迎以各种方式支持,这也是对古柳输出教程的一种正向鼓励!
最后欢迎加入「可视化交流群」
,进群多多交流,对本文任何地方有疑惑的可以群里提问。加古柳微信:xiaoaizhj
,备注「可视化加群」
即可。
欢迎关注古柳的公众号「牛衣古柳」
,并设置星标,以便第一时间收到更新。
本文转载自: 掘金