2D 精灵着色器:Gradient

    对于任何持有 CustomMaterial 属性的 UI 和 2D 组件,都可在 属性检查器 内通过该属性的下拉框选择或者从 资源管理器 内拖拽实现自定义材质。

    引擎规定 UI 组件的自定义材质只能有一个。

    本文将通过实现一个精灵的渐变着色器来演示如何为 UI 和 2D 组件使用自定义着色器。

    通过 CocosDashBoard 创建一个新的 2D 项目。

    创建一个新的场景并在场景内添加一个 Sprite:

    create sprite

    资源管理器 内执行以下的操作:

    • 创建名为 gradient.effect 的着色器文件
    • 拷贝 资源管理器 -> intenal -> effects 内的 着色器的内容到 gradient.effect 内
    • 创建名为 gradient.mtl 的材质并在 属性查看器 内的 Effect 栏选择 gradient.effect
    • 导入任意的纹理

    材质和着色器的创建可通过在 资源管理器 内任意空白处点击鼠标右键,或单击 资源管理 上的 + 按钮

    创建好的工程如图示:

    选中创建好的精灵,将 gradient.mtl 材质和导入的纹理分别赋予给精灵的对应属性:

    custom-material

    通过观察可得知,渐变可以理解为在某个轴上,随着坐标变化,颜色发生变化的现象。因此在 CCEffect 段内给着色器的 properties 增加两个颜色属性分别代表渐变的起始颜色和结束颜色。

    此时的 CCEffect:

    1. CCEffect %{
    2. techniques:
    3. - passes:
    4. - vert: sprite-vs:vert
    5. depthStencilState:
    6. depthTest: false
    7. depthWrite: false
    8. blendState:
    9. targets:
    10. - blend: true
    11. blendSrc: src_alpha
    12. blendDst: one_minus_src_alpha
    13. blendDstAlpha: one_minus_src_alpha
    14. cullMode: none
    15. properties:
    16. alphaThreshold: { value: 0.5 }
    17. startColor: { value: [1.0, 1.0, 1.0, 1.0], editor: {type: color} }
    18. endColor: { value: [1.0, 1.0, 1.0, 1.0], editor: {type: color} }

    注意这里定义了两个颜色值 startColorendColor,如果要将这两个颜色正确的传入给着色器片段,则需要增加对应的 Uniform。

    引擎规定,不允许离散使用 Uniform,因此在 CCProgram sprite-fs 段内添加下列的代码:

    此时引擎会自动将 properties 内定义的属性和 Constant 内的 Uniform 进行关联。

    通常不用对顶点着色器做额外的处理,因此保留系统内置的 sprite-vs

    在默认的精灵着色器内,精灵顶点的 XY 轴和纹理坐标的 UV 是对应的,因此可考虑使用纹理坐标的变化来达成渐变,在 USE_TEXTURE 宏定义的范围内增加下列代码:

    1. #if USE_TEXTURE
    2. o *= CCSampleWithAlphaSeparated(cc_spriteTexture, uv0);
    3. #if IS_GRAY
    4. o.r = o.g = o.b = gray;
    5. #endif
    6. // 根据 UV 的变化来调整渐变色
    7. o.rgb *= mix(startColor, endColor, vec4(uv0.x)).rgb;
    8. #endif

    勾选原有材质上的 USE_TEXTURE 选项:

    此时通过调整材质上的 startColorendColor 则可以观察到不同的渐变:

    material-color

    精灵着色的变化:

    在上述的片元着色器内,只考虑了纹理坐标轴 U 的渐变,为了灵活性和支持更多的功能,通过预处理宏定义来实现不同轴的渐变,因此删掉下列代码:

    添加下列代码:

    1. #if USE_HORIZONTAL
    2. o.rgb *= mix(startColor, endColor, vec4(uv0.x)).rgb;
    3. #endif
    4. #if USE_VERTICAL
    5. #endif

    这里声明了 USE_HORIZONTAL 和 这两个预处理宏定义,分别代表了水平方向和垂直方向的渐变,可以方便地按需使用:

    完整的着色器代码: