<七>Cocos Shader语法
Cocos Creator 中的着色器(Cocos Shader ,文件扩展名为 *.effect),是一种基于 YAML 和 GLSL 的单源码嵌入式领域特定语言(single-source embedded domain-specific language),YAML 部分声明流程控制清单,GLSL 部分声明实际的 Shader 片段,这两部分内容相互补充,共同构成了一个完整的渲染流程描述。
备注:如果使用VSCode编辑器编写 Cocos Shader,可在扩展商店中安装Cocos Effect 扩展,提供编写时的语法高亮提示。

1 Cocos Shader语法
1.1 语法结构 | 文件框架
Cocos Shader 通常由两个部分组成:
- CCEffect:用于声明渲染技术(Technique)、渲染过程(Pass)、渲染状态、材质参数等属性。
- CCProgram:用于声明顶点着色器(Vertex Shader)和片元着色器(Fragment Shader)代码片段。
这里以引擎内置的无光照着色器 builtin-unlit.effect 为例解析CocosShader的语法框架
1.1.1 创建Shader文件
内置的着色器是不可编辑。如果想要其变成可编辑的,就需要Copy一份到assets的子目录下。
双击打开Copy的着色器:
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
CCEffect %{
techniques:
- name: opaque
passes:
- vert: unlit-vs:vert
frag: unlit-fs:frag
properties: &props
mainTexture: { value: grey }
tilingOffset: { value: [1, 1, 0, 0] }
mainColor: { value: [1, 1, 1, 1], linear: true, editor: { type: color } }
colorScale: { value: [1, 1, 1], target: colorScaleAndCutoff.xyz }
alphaThreshold: { value: 0.5, target: colorScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } }
color: { target: mainColor, linear: true, editor: { visible: false } } # backward compability
migrations: &migs
properties:
mainColor: { formerlySerializedAs: color }
- name: transparent
passes:
- vert: unlit-vs:vert
frag: unlit-fs:frag
depthStencilState: &d1
depthTest: true
depthWrite: false
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
blendDstAlpha: one_minus_src_alpha
properties: *props
migrations: *migs
- name: add
passes:
- vert: unlit-vs:vert
frag: unlit-fs:frag
rasterizerState: &r1 { cullMode: none }
depthStencilState: *d1
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one
blendSrcAlpha: src_alpha
blendDstAlpha: one
properties: *props
migrations: *migs
- name: alpha-blend
passes:
- vert: unlit-vs:vert
frag: unlit-fs:frag
rasterizerState: *r1
depthStencilState: *d1
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
blendSrcAlpha: src_alpha
blendDstAlpha: one_minus_src_alpha
properties: *props
migrations: *migs
}%
CCProgram unlit-vs %{
precision highp float;
#include <legacy/input>
#include <builtin/uniforms/cc-global>
#include <legacy/decode-base>
#include <legacy/local-batch>
#include <legacy/input>
#include <legacy/fog-vs>
#if USE_VERTEX_COLOR
in lowp vec4 a_color;
out lowp vec4 v_color;
#endif
#if USE_TEXTURE
out vec2 v_uv;
uniform TexCoords {
vec4 tilingOffset;
};
#endif
vec4 vert () {
vec4 position;
CCVertInput(position);
mat4 matWorld;
CCGetWorldMatrix(matWorld);
#if USE_TEXTURE
v_uv = a_texCoord * tilingOffset.xy + tilingOffset.zw;
#if SAMPLE_FROM_RT
CC_HANDLE_RT_SAMPLE_FLIP(v_uv);
#endif
#endif
#if USE_VERTEX_COLOR
v_color = a_color;
#endif
CC_TRANSFER_FOG(matWorld * position);
return cc_matProj * (cc_matView * matWorld) * position;
}
}%
CCProgram unlit-fs %{
precision highp float;
#include <legacy/output-standard>
#include <legacy/fog-fs>
#if USE_ALPHA_TEST
#pragma define-meta ALPHA_TEST_CHANNEL options([a, r, g, b])
#endif
#if USE_TEXTURE
in vec2 v_uv;
uniform sampler2D mainTexture;
#endif
uniform Constant {
vec4 mainColor;
vec4 colorScaleAndCutoff;
};
#if USE_VERTEX_COLOR
in lowp vec4 v_color;
#endif
vec4 frag () {
vec4 o = mainColor;
o.rgb *= colorScaleAndCutoff.xyz;
#if USE_VERTEX_COLOR
o.rgb *= SRGBToLinear(v_color.rgb);//use linear
o.a *= v_color.a;
#endif
#if USE_TEXTURE
vec4 texColor = texture(mainTexture, v_uv);
texColor.rgb = SRGBToLinear(texColor.rgb);
o *= texColor;
#endif
#if USE_ALPHA_TEST
if (o.ALPHA_TEST_CHANNEL < colorScaleAndCutoff.w) discard;
#endif
CC_APPLY_FOG(o);
return CCFragOutput(o);
}
}%
代码块折叠一下,可以看到有三部分内容:

实际对应的就是上面所说的CCEffect和CCProgram(顶点着色器和片元着色器)
1.1.2 CCEffect
在语法上:
CCEffect %{
# 符合YAML语法结构的渲染流程描述信息
}%
在 Cocos Shader 中,由 CCEffect 包裹的部分是由 YAML 语法 声明的渲染流程相关的描述信息。
- techniques
![image]()
CCEffect包含了一个对象techniques,对象的值是一个数组。在Cocos Shader中,techniques是一个渲染技术数组,一个 CCEffect 中支持定义多个渲染技术,但在实际渲染时,同一个材质实例只能应用其中一个技术。
以该Shader为例,其中包含了 4 个技术:- opaque
- transparent
- add
- alpha-blend
opaque 专门用于渲染不透明物体的渲染技术,transparent,add,alpha-blend 则用来渲染半透明物体。
语法:
techniques:
- name: 渲染技术名
passes:
-xxx
-xxx
...
- name: 渲染技术名
...
- 渲染技术
这里以opaque为例,展开代码块如下
- name: opaque
passes:
- vert: unlit-vs:vert
frag: unlit-fs:frag
properties: &props
mainTexture: { value: grey }
tilingOffset: { value: [1, 1, 0, 0] }
mainColor: { value: [1, 1, 1, 1], linear: true, editor: { type: color } }
colorScale: { value: [1, 1, 1], target: colorScaleAndCutoff.xyz }
alphaThreshold: { value: 0.5, target: colorScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } }
color: { target: mainColor, linear: true, editor: { visible: false } } # backward compability
migrations: &migs
properties:
mainColor: { formerlySerializedAs: color }
每个渲染技术(technique)都包含了名称(name)和渲染过程(passes)
名称用于标记渲染技术的用途,渲染过程则定义了一个完整的渲染流程所需要的全部信息。
一个渲染技术可以包含多个渲染过程,渲染过程会按定义的先后顺序逐一执行
渲染过程(pass):
比对上述代码,一个渲染过程中,必须包含一个顶点着色器(Vertex Shader,VS)和一个片元着色器(Fragment Shader,FS),properties 和 migrations 都是可选配置参数项。
VS/FS 着色器需要指定使用的 CCProgram ,以及指定着色器的入口函数。 如果不指定入口函数,会默认使用 main。
一个渲染过程的语法结构如下:
- vert: CCProgram声明的顶点着色器名:顶点着色器的入口函数名
frag: CCProgram声明的片元着色器名:片元着色器的入口函数名
...
...
每个渲染过程都只有 vert 和 frag 两个必填参数,分别用于声明当前渲染过程使用的顶点着色器和片元着色器,格式为 片段名: 入口函数名。
片段名可以是本文件中声明的 CCProgram 片段名,也可以是引擎提供的标准头文件。
需要注意:自定义着色器的代码中不应该使用 main 函数,Cocos Shader 在编译时会自动添加一个 main 函数并调用渲染过程的入口函数(例如 vert 或 frag),main 函数会将入口函数的返回值作为当前 Shader 的输出(例如 gl_Position 或 gl_FragColor)。
示例代码中一个pass的元素还有一部分没有提到:
- 渲染过程属性
渲染过程属性部分是渲染过程中的可选配置参数,以properties为例:
properties 用于将 Shader 中定义的 uniform 进行别名映射。这个映射可以是某个 uniform 的完整映射,也可以是具体某个分量的映射(使用 target 参数)
渲染过程中的 properties 用于配置相关属性描述。通过它,可以定义一个 uniform修饰的全局变量 在面板上的显示方式
CCEffect %{
techniques:
- name: opaque # 定义一个不透明的渲染技术
passes:
- vert: vs: entry # 选择一个 CCProgram 声明的顶点着色器 ‘vs’,入口函数是 ‘entry’
frag: fs: entry # 选择一个 CCProgram 声明的片元着色器 ‘fs’,入口函数是 ‘entry’
properties:
mainTexture: { value: grey } # 着色器中需要同步定义一个 ‘uniform mainTexture’,该属性可在编辑器的属性检查器中进行配置
colorScale: { value: [1, 1, 1], target: colorScaleAndCutoff.xyz } # 基于 ‘target’ 属性配置机制,着色器中需要同步定义一个 ‘uniform colorScaleAndCutoff’,并选取它的 x、y、z 分量填充 ‘colorScale’ 设置的数据
depthStencilState: # 配置深度测试、模板测试和写入状态
depthTest: true
depthWrite: true
...
...
}%
其他的可选配置可参考:https://docs.cocos.com/creator/3.8/manual/zh/shader/pass-parameter-list.html
1.1.3 CCProgram
在 Cocos Shader 中由 CCProgram 包裹的部分是由 GLSL 语法 声明的 Shader 片段
语法结构:
CCProgram shader-name %{
<required: precision settings>
<optional: include>
<optional: ubo>
<optional: custom attribute>
<optional: >
vec4 entry(){
// 需要返回一个 vec4 类型数据
}
}%
1.1.4 预处理宏定义
通过预处理宏,可在 Cocos Shader 编译时控制代码分支和组合,以实现高效便捷的 Shader 代码管理。
详细的介绍参考:https://docs.cocos.com/creator/3.8/manual/zh/shader/macros.html

浙公网安备 33010602011771号