creator-shader记录
creator-shader记录
前篇
- 官方
- 着色器创建与使用 - https://docs.cocos.com/creator/manual/zh/shader/effect-inspector.html
- 着色器语法 - https://docs.cocos.com/creator/manual/zh/shader/effect-syntax.html
- 2D 精灵着色器:Gradient - https://docs.cocos.com/creator/manual/zh/shader/write-effect-2d-sprite-gradient.html
- 宏的使用范围 - https://docs.cocos.com/creator/manual/zh/shader/macros.html#%E5%AE%8F%E7%9A%84%E4%BD%BF%E7%94%A8%E8%8C%83%E5%9B%B4
- Cocos Shader 内置全局 Uniform - https://docs.cocos.com/creator/manual/zh/shader/uniform.html
- 用 Shader 写个完美的波浪 - https://forum.cocos.org/t/topic/97927
动态加载 shader 及 材质
动态设置参数
通过启用宏来暴露参数
通过 editor.parent 指定对应 宏, 启用宏时才显示这个属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32properties:
alphaThreshold: { value: 0.5, target: colorScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } }
---
### 输入输出变量定义
也就是
- 顶点着色器
```json
CCProgram sprite-vs %{
// application -> vertex
in vec3 a_position;
in vec2 a_texCoord;
in vec4 a_color;
// vertex -> fragment
out vec4 color;
out vec2 uv0;
out vec2 uv1;
vec4 vert () {
vec4 pos = vec4(a_position, 1);
pos = cc_matViewProj * pos;
return pos; // 返回剪裁空间下的坐标
}
}%像素着色器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45CCProgram sprite-fs %{
// vertex -> fragment, 需要和像素着色器一致
in vec4 color;
in vec2 uv0;
in vec2 uv1;
vec4 frag () {
vec4 mainVal = CCSampleWithAlphaSeparated(mainTexture, vec2(uv0.x + speed, uv0.y));
return mainVal; // 最终显示的颜色
}
}%
---
### unitform 变量定义
1. 如果需要暴露到编辑器的参数, 都写到 *properties* 中
```json
CCEffect %{
properties:
mainTexture: { value: grey }
mainTilingOffset: { value: [1, 1, 0, 0] }
colorB: { value: [0.2432, 0.2432, 0.2432, 1.0], editor: { type: color, tooltip: '颜色' } }
colorC : { valu: [0.1, 0.0]}
mask01Uspeed : { { valu: 1.0}, editor: { parent: 'MASK01', displayName: 'Uspeed' } }
mask01Vspeed : { { valu: 1.0}, editor: { parent: 'MASK01', displayName: 'Vspeed' } }
}%
2. 在 *像素着色器*, *Constant* 中
```json
CCProgram sprite-fs %{
uniform Constant {
vec4 colorB;
vec2 colorC;
float mask01Uspeed;
float mask01Vspeed;
};
}%- uniform 定义顺序要遵循字节对齐原则, 大的在上面, 小的在下面, 否则会报错:
Error EFX2205: UBO 'Constant' introduces implicit padding: 8 bytes before 'xxx', consider re-ordering the members
- uniform 定义顺序要遵循字节对齐原则, 大的在上面, 小的在下面, 否则会报错:
在 顶点着色器, 都放在 TexCoords 中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24CCProgram sprite-vs %{
uniform TexCoords {
vec4 mainTilingOffset;
float mask01Uspeed;
float mask01Vspeed;
};
}%
4. 编辑器效果

---
### 编辑显示参数
- 属性定义
```json
properties:
_VSpeed_diffusem : { { value: 0.0}, target: colorScaleAndCutoff.x, editor: { parent: '_DIFFUSEMASK_ON', displayName: 'Vspeed', slide: true, range: [0, 1.0], visible: false, type: 'color', tooltip: '颜色 B' } }value
: 是默认值, 可以是0.5, [0.5, 0.5], [0.5, 0.5, 0.5, 0.5]
target
: 可以将面板上的这个值, 映射到某个 unitform 或者其分量上editor
: 是编辑器显示设置parent
: 指定的是代码中使用到的宏, 在编辑器中勾选 启用宏, 这些参数就会显示出来, 并在同一个区域中slide
: 表示是否是滚动条displayName
: 显示的名字range
: 值的范围约束visible
: 显示 or 隐藏type: 'color'
: 指定类型为颜色tooltip
: 弹窗提示
颜色
属性定义
1
2properties:
colorB: { value: [0.2432, 0.2432, 0.2432, 1.0], editor: { type: color, tooltip: '颜色 B' } }效果
实际一段翻译 unity shaderlab 代码
unity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#if _DIFFUSEMASK_ON
#if _DIFFUSEMASKRO_ON
float DiffuseMaskAng_cos;
float DiffuseMaskAng_sin;
sincos(0.0174*_DiffuseMaskAng, DiffuseMaskAng_sin, DiffuseMaskAng_cos);
//uv旋转前将旋转中心移到uv中心
vec2 panner1=mul(v.texcoord0- vec2(0.5,0.5),half2x2( DiffuseMaskAng_cos, -DiffuseMaskAng_sin, DiffuseMaskAng_sin, DiffuseMaskAng_cos))+ vec2(0.5,0.5)+_Time.y*float2(_USpeed_diffusem, _VSpeed_diffusem);
#else
float2 panner1=v.texcoord0+_Time.y*float2(_USpeed_diffusem, _VSpeed_diffusem);
#endif
o.uv0 = TRANSFORM_TEX(panner1, _DiffuseMaskTex);
#endifcocos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35properties:
mainTexture: { value: grey }
mainTilingOffset: { value: [1, 1, 0, 0] }
_DiffuseMaskAng : {{ value: 0.0}, editor: { step: 1, parent: '_DIFFUSEMASK_ON', displayName: '旋转角度'}}
_USpeed_diffusem : { { value: 0.0}, editor: { parent: '_DIFFUSEMASK_ON', displayName: 'Uspeed' } }
_VSpeed_diffusem : { { value: 0.0}, editor: { parent: '_DIFFUSEMASK_ON', displayName: 'Vspeed' } }
uniform TexCoords {
vec4 mainTilingOffset;
float _DiffuseMaskAng;
float _USpeed_diffusem;
float _VSpeed_diffusem;
};
#if _DIFFUSEMASK_ON
#if _DIFFUSEMASKRO_ON
float DiffuseMaskAng_cos;
float DiffuseMaskAng_sin;
DiffuseMaskAng_sin = sin(0.0174*_DiffuseMaskAng);
DiffuseMaskAng_cos = cos(0.0174*_DiffuseMaskAng);
//uv旋转前将旋转中心移到uv中心
vec2 panner1=(a_texCoord- vec2(0.5,0.5)) * mat2( DiffuseMaskAng_cos, -DiffuseMaskAng_sin, DiffuseMaskAng_sin, DiffuseMaskAng_cos) + vec2(0.5,0.5)+cc_time.y*vec2(_USpeed_diffusem, _VSpeed_diffusem);
#else
vec2 panner1=a_texCoord+cc_time.y*vec2(_USpeed_diffusem, _VSpeed_diffusem);
#endif
uv0 = panner1 * mainTilingOffset.xy + mainTilingOffset.zw;
#else
uv0 = a_texCoord;
#endif- mul 直接换成两个矩阵 * 即可
- float2/half2 都换成对应的 vec2
- half2x2 换成 mat2
- sincos 换成 sin 和 cos 计算
踩坑
float 变量要定义有小数点的值
- 如果定义成
float aaa= 0;
, 报错:cannot convert from 'const int' to 'highp float'
- 正确使用是
float aaa= 0.0;
animation k 材质参数不生效
- 使用 3.6.3 的引擎出现了这个问题
- 解决办法 升级到 3.7.2+ 版本就没这个问题了
2d uv 采样 编辑器正常, 运行不正常
在自定义的 shader 里加了个 贴图, 然后用 uv 去采样, 发现编辑器里正常采样, 运行时采样不正常
原因是: 导入到编辑器里的贴图, 设置为 sprite 类型的话, 默认会自动勾上 Packable, 也就是说图片会运行时合到一个大图中, 从而改图的的 uv 就变成不是 (0 或 1), 而是 0.x, 从而导致如是用了这个 uv 值去采样自定义贴图的话, 就不能得到正确的结果
解决办法, 有两种情况
- 如果需要用到 sprite 贴图的采样值的话, 只能勾选 Packable, 不自动合到大图
- 如果不需要用 sprite 贴图的话, 可以创建一个很小的无用贴图, 然后勾选 Packable
参考官网说明:
https://docs.cocos.com/creator/manual/zh/asset/sprite-frame.html#packable
Packable
如果引擎开启了 动态合图 功能,动态合图会自动将合适的贴图在开始场景时动态合并到一张大图上来减少 Drawcall。但是将贴图合并到大图中会修改原始贴图的 UV 坐标,如果在自定义 effect 中使用了贴图的 UV 坐标,这时 effect 中的 UV 计算将会出错,需要将贴图的 Packable 属性设置为 false 来避免贴图被打包到动态合图中。
编辑器开发运行正常, 打包后运行不正常
- 加载报错:
Failed to load resource: the server responded with a status of 404 (Not Found)
- 原因还是 Packable 的问题, 就是 shader 里面用的 贴图的 Packable 打勾了, 引发了这个报错
- 解决办法: shader 里面用到贴图, 都不能勾选 Packable, 需要拷贝出一份, 修改为 Texture 类型的贴图