本公众号由以下老铁赞助,感谢他们❗️
玉兔小姐姐,最近一直都在研究各种游戏特效,写了不少 Shader,有 3D 的,也有 2D 的,被Shader折磨已久的老铁们有福了。
听玉兔说,为了研究 2D Shader 她熬夜玩了数十款游戏,眼睛都玩肿了!
目前有部分 Shader 已经上架,等不及的小伙伴可以移步 Cocos Store 商城,抢先学习,快人一步!2D Shader 特效包,包含十大实用Shader及配套教程。
特效包中的 Shader 均是 2D 游戏开发中经常用到的,不同的是,玉兔给其中的每一个特效都配套了相应的文章教程,这样大家不用担心读不懂代码,看不懂原理。
目前上新5折特价,有需要的朋友可以直接冲!购买了的朋友请联系玉兔获取对应的教程!
2D Shader 特效包链接:https://store.cocos.com/app/detail/6580
广告打完了,正式回到今天的主题,看玉兔带大家用程序化修改材质属性。
在修改材质时,常规操作是更改 Shader 代码,但其实也可以用程序来操作材质,那今天带大家使用 TS 修改材质的颜色和纹理。
老规矩,不想看文字的话,可以点击下方视频,别忘了给玉兔送颗小红心!爱你们!比心!
TS 修改材质属性
要对材质进行相关编程,建议大家先通读一遍 Cocos 官方文档:
功能模块 -> 图形渲染 -> 材质系统
官方文档链接:https://docs.cocos.com/creator/3.8/manual/zh/material-system/overview.html
用 TS 修改材质的属性,主要有以下几个步骤:
1. 使用 sharedMaterial 访问材质
let mat = this.meshRenderer.sharedMaterial;
访问材质时,需要避免产生新的材质实例,要使用 sharedMaterial。
2. 使用 setProperty 修改材质属性
修改材质属性时,使用 setProperty 方法,setProperty 的使用如下:
setProperty(目标 Uniform 名称, 需要设置的目标值)
假设在某个材质的 Shader 中,控制颜色的变量名称为 mainColor,要把材质颜色修改为红色,只需要按以下写法即可,注意颜色要用 0~255 表示。
mat.setProperty('mainColor', color(255, 0, 0, 255));
使用 setProperty 修改纹理变量时,操作同理。
mat.setProperty('mainTexture', tex);
3. 通过 pass 修改材质
如果想频繁修改材质的属性,例如每秒修改一次材质颜色、每秒修改一次材质纹理,使用 setProperty 就不太合适。
这是由于 setProperty 是通过属性的名称来进行查找和设置,它每次都会检索完所有 pass,如果使用 setProperty 进行频繁的属性更改,就太过复杂。
如果在对应的 pass 上直接修改,事情就会变简单很多。
(1)通过 pass 修改材质 uniform 变量
对于修改颜色这类 uniform 变量,核心是需要获取到变量的 handle。
什么是 handle 呢?
假设有一个书架,书架上有很多书,每本书都有一个特定的编号,这个编号就是这本书的标识符。
当我们想要找某本书的时候,只需要记住这本书的编号,就能很快的找到这本书,而非记住书的名字、作者等其他信息。
在 Shader 中,有很多 uniform 变量,比如颜色、光照参数,这些 uniform 变量相当于图书馆中的很多书,而 handle 就是这些书的编号。
由于 setProperty 是通过属性名称直接设置属性值,它每次调用时都需要通过属性名进行查找和设置,相当于根据书名一本一本的查找。
而通过 handle 这样的“书本编号”查找,访问速度更快,效率也更高。
要获取 handle,通常使用 getHandle 方法;修改变量时,则使用 setUniform 方法,setUniform 的使用如下图:
假设要频繁修改 mainColor 的颜色,写成代码的形式如下:
let pass = mat.passes[0];
let handle = pass.getHandle('mainColor');
pass.setUniform(this._handle, color(r, g, b, a));
(2)修改纹理变量
和频繁修改 uniform 变量类似,频繁修改纹理变量最好也是通过 pass 直接修改。不同的是,修改纹理变量的关键是获取到纹理变量的 binding。
那什么又是 binding 呢?
其实 binding 和 handle 的作用是一样的,可以理解为 uniform 变量需要用 handle 去索引,而 纹理变量 需要用 binding 去索引。
代码实现形式也和上面类似:
let pass = mat.passes[0];
let binding = pass.getBinding('mainTexture');
pass.bindTexture(binding,tex);
写在最后
今天的内容比较简单,核心是对 handle 和 binding 的理解,欢迎大家关注玉兔的视频号和公众号,获取第一手信息和干货!
游戏开发,副业变现
晓衡的愿景是助力 1000 位个人开发者
一年独立挣钱10W+
欢迎加晓衡微信