2D 精灵着色器:Gradient
对于任何持有 CustomMaterial 属性的 UI 和 2D 组件,都可在 属性检查器 内通过该属性的下拉框选择或者从 资源管理器 内拖拽实现自定义材质。
引擎规定 UI 组件的自定义材质只能有一个。
本文将通过实现一个精灵的渐变着色器来演示如何为 UI 和 2D 组件使用自定义着色器。
通过 CocosDashBoard 创建一个新的 2D 项目。
创建一个新的场景并在场景内添加一个 Sprite:
在 资源管理器 内执行以下的操作:
- 创建名为 gradient.effect 的着色器文件
- 拷贝 资源管理器 -> intenal -> effects 内的 着色器的内容到 gradient.effect 内
- 创建名为 gradient.mtl 的材质并在 属性查看器 内的 Effect 栏选择 gradient.effect
- 导入任意的纹理
材质和着色器的创建可通过在 资源管理器 内任意空白处点击鼠标右键,或单击 资源管理 上的 +
按钮
创建好的工程如图示:
选中创建好的精灵,将 gradient.mtl 材质和导入的纹理分别赋予给精灵的对应属性:
通过观察可得知,渐变可以理解为在某个轴上,随着坐标变化,颜色发生变化的现象。因此在 CCEffect 段内给着色器的 properties 增加两个颜色属性分别代表渐变的起始颜色和结束颜色。
此时的 CCEffect:
CCEffect %{
techniques:
- passes:
- vert: sprite-vs:vert
depthStencilState:
depthTest: false
depthWrite: false
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
blendDstAlpha: one_minus_src_alpha
cullMode: none
properties:
alphaThreshold: { value: 0.5 }
startColor: { value: [1.0, 1.0, 1.0, 1.0], editor: {type: color} }
endColor: { value: [1.0, 1.0, 1.0, 1.0], editor: {type: color} }
注意这里定义了两个颜色值 startColor
和 endColor
,如果要将这两个颜色正确的传入给着色器片段,则需要增加对应的 Uniform。
引擎规定,不允许离散使用 Uniform,因此在 CCProgram sprite-fs
段内添加下列的代码:
此时引擎会自动将 properties
内定义的属性和 Constant
内的 Uniform 进行关联。
通常不用对顶点着色器做额外的处理,因此保留系统内置的 sprite-vs
。
在默认的精灵着色器内,精灵顶点的 XY 轴和纹理坐标的 UV 是对应的,因此可考虑使用纹理坐标的变化来达成渐变,在 USE_TEXTURE 宏定义的范围内增加下列代码:
#if USE_TEXTURE
o *= CCSampleWithAlphaSeparated(cc_spriteTexture, uv0);
#if IS_GRAY
o.r = o.g = o.b = gray;
#endif
// 根据 UV 的变化来调整渐变色
o.rgb *= mix(startColor, endColor, vec4(uv0.x)).rgb;
#endif
勾选原有材质上的 USE_TEXTURE
选项:
此时通过调整材质上的 startColor 和 endColor 则可以观察到不同的渐变:
精灵着色的变化:
在上述的片元着色器内,只考虑了纹理坐标轴 U 的渐变,为了灵活性和支持更多的功能,通过预处理宏定义来实现不同轴的渐变,因此删掉下列代码:
添加下列代码:
#if USE_HORIZONTAL
o.rgb *= mix(startColor, endColor, vec4(uv0.x)).rgb;
#endif
#if USE_VERTICAL
#endif
这里声明了 USE_HORIZONTAL
和 这两个预处理宏定义,分别代表了水平方向和垂直方向的渐变,可以方便地按需使用:
完整的着色器代码: