title: creator-shader记录
categories: Cocos2dx
tags: [creator, shader, 渲染]
date: 2023-03-29 21:16:51
comments: false
mathjax: true
toc: true
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 及 材质
- 程序化使用材质 - https://docs.cocos.com/creator/manual/zh/material-system/material-script.html
动态设置参数
- Pass 可选配置参数 - https://docs.cocos.com/creator/manual/zh/shader/pass-parameter-list.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
-
通过 editor.parent 指定对应 宏, 启用宏时才显示这个属性
properties: alphaThreshold: { value: 0.5, target: colorScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } }
输入输出变量定义
也就是
-
顶点着色器
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; // 返回剪裁空间下的坐标 } }%
-
像素着色器
CCProgram 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 变量定义
-
如果需要暴露到编辑器的参数, 都写到 properties 中
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' } } }%
-
在 像素着色器, Constant 中
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 中
CCProgram sprite-vs %{ uniform TexCoords { vec4 mainTilingOffset; float mask01Uspeed; float mask01Vspeed; }; }%
-
编辑器效果
编辑显示参数
-
属性定义
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
: 弹窗提示
-
-
颜色
-
属性定义
properties: colorB: { value: [0.2432, 0.2432, 0.2432, 1.0], editor: { type: color, tooltip: '颜色 B' } }
-
效果
实际一段翻译 unity shaderlab 代码
-
unity
#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); #endif
-
cocos
properties: 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 类型的贴图