// Effect Syntax Guide: https://docs.cocos.com/creator/manual/zh/shader/index.html
CCEffect %{
techniques: #标准结构,在 Cocos Shader 中,由 CCEffect 包裹的部分是由 YAML 语法 声明的渲染流程相关的描述信息。
- name: opaque #标准结构,CCEffect包含了一个对象techniques,对象的值是一个数组。在Cocos Shader中,techniques是一个渲染技术数组,一个 CCEffect 中支持定义多个渲染技术,但在实际渲染时,同一个材质实例只能应用其中一个技术。
passes: # 标准结构,passes对象是一个渲染过程数组,一个passes可以包含多个渲染过程
- vert: vs:vert # 标准结构,vert对象: 顶点shader名称:顶点shader入口函数名
frag: fs:frag # 同上,注意vert和frag是必填参数,PipelineStates还有很多可选配置参数,可参考官方文档
#实际上,Pass 中的参数主要分两个部分:
#引擎提供的用于控制渲染管线状态的 PipelineStates
#开发者可自定义的 属性检查器 面板参数 properties
properties:
# 开发者可自定义的 属性检查器 面板参数,用于将 Shader 中定义的 uniform 进行别名映射,这个映射可以是某个 uniform 的完整映射,也可以是具体某个分量的映射(使用 target 参数)
#默认情况下,properties 中定义的属性参数会暴露并显示在编辑器的 属性检查器 面板中,方便进行可视化控制。
#如果不想显示在 属性检查器 面板上,可在定义属性时加上 editor: { visible: false }
mainTexture: { value: white } #这个就是sprite对应的texture参数,该属性可在编辑器的属性检查器中进行配置,注意着色器中需要同步定义一个 ‘uniform mainTexture’,
mainColor: { value: [1, 1, 1, 1], editor: { type: color } } #类上,自定义的数据可以传递给shader
#properties还有很多可配置的参数,具体可参考官方文档
- name: transparent #定义一个半透明的transparent渲染技术,在CocosCreator中,transparent,add,alpha-blend 则用来渲染半透明物体
passes:
- vert: vs:vert
frag: fs:frag
blendState: # PipelineStates的可选配置,描述材质混合状态
targets: # 混合目标数组
- blend: true # 是否开启混合
blendSrc: src_alpha #指定 混合源 的 RGB 混合因子
blendDst: one_minus_src_alpha #指定 混合目标 的 RGB 混合因子
blendSrcAlpha: src_alpha #指定 混合源 的 Alpha 混合因子
blendDstAlpha: one_minus_src_alpha #指定 混合目标 的 Alpha 混合因子
#以上以及更多混合配置在官方文档中都有介绍,也可上网查一下混合模式的原理和效果
}%
CCProgram vs %{//标准结构,顶点着色器,“vs”可自定义命名,在 Cocos Shader 中由 CCProgram 包裹的部分是由 GLSL 语法 声明的 Shader 片段,一个shader过程必须包含顶点着色器和片元着色器
precision highp float; //precision是GLSL用于声明浮点数或定点数精度修饰符的关键字,highp是精度限定符,float是限定类型
//用于指定整型或浮点型变量的精度。精度限定符可使着色器的编写者明确定义着色器变量计算时使用的精度。
//在 在 Shader 头部声明的精度应用于整个 Shader,是所有基于浮点型的变量的默认精度,同时也可以定义单个变量的精度。在 Shader 中如果没有指定默认精度,则所有的整型和浮点型变量都采用高精度计算。
#include <builtin/uniforms/cc-local>
//类似c++,如果要使用内置全局变量,包含对应的着色器片段(Chunk)即可
//在资源管理器的internal/chunks目录下可查看可以包含的着色器片段,如在cc-local.chunk中就有cc_matWorld mat4 模型空间转世界空间矩阵
//cc_matWorldIT mat4 模型空间转世界空间逆转置矩阵,如果在着色器中使用这些变量,只需要包含该chunck即可
#include <builtin/uniforms/cc-global>
//同上,例如想要获取时间(秒)又不想传入时间参数,就可以包含cc-global,其他的变量可参考官方文档
in vec3 a_position;//声明一个输入变量(顶点位置)。“in”是参数限定符,如果限定符缺省,默认为“in”。
//in会把修饰的变量复制到函数中,并在在函数中可读写,实际上传入函数的是实参的一份拷贝,在函数中修改in修饰的形参不会影响到实参本身
//'vec3'声明参数为包含3个浮点数的向量
//一般来说变量的命名前缀为‘a_’表示输入的变量,当然完全可以自定义
in vec4 a_color;//输入的顶点颜色,一个包含了4个浮点数的向量,可对应rgba值
out vec4 v_color;//声明一个输出变量v_color(顶点颜色传给fs使用),‘out’会把修饰的变量在函数返回时从函数中复制出来
//out的作用是向函数外部传递新值,out模式下传递进来的参数是write-only的(可写不可读).就像是一个"坑位",坑位中的值需要函数给他赋予.
//在函数中,修改out修饰的形参会影响到实参本身
//还有一种函数参数限定符“inout”,inout修饰的形参可以被理解为是一个带值的"坑位",及可读也可写,在函数中,修改inout修饰的形参会影响到实参本身.
#if USE_TEXTURE //GLSL 允许定义和 C 语言类似的宏定义,预处理宏定义允许着色器定义多样化的动态分支,确定最终的渲染效果
in vec2 a_uv0; //这里表示如果使用纹理,输入纹理坐标,一定要注意,纹理坐标是二维向量,数值为0-1
out vec2 v_uv0; //输出纹理坐标
#endif
//顶点着色器的入口函数声明
vec4 vert () {
vec4 pos = vec4(a_position,1);//顶点位置是vec3,需要转换成vec4才能使用4*4的矩阵变换(位移、旋转、缩放)
#if CC_USE_MODEL //如果使用模型,则将位置通过世界矩阵进行投影(2D不用管)
pos = cc_matViewProj * cc_matWorld * pos;
#else
//在顶点着色器中,将3D顶点位置转换为裁剪空间坐标是一个标准步骤。这通常涉及到使用模型视图投影矩阵(cc_matViewProj)将顶点从模型空间转换到裁剪空间。
//这个过程包括了模型变换、视图变换和投影变换,最终结果是顶点在裁剪空间中的位置,该位置随后会被光栅化器用于生成屏幕上的图像。
pos = cc_matViewProj * pos;//使用视图投影变换,opengl会将图片进行变换,最终显示
#endif
#if USE_TEXTURE
v_uv0 = a_uv0; //要传给fs的纹理坐标
#endif
v_color = a_color;//要传给fs的顶点颜色
return pos;
//注意:顶点shader必须返回一个四维向量(裁剪坐标),如上return pos
//这个变量用于指定顶点在裁剪空间中的位置,其值将直接影响到渲染对象最终在屏幕上的显示位置
//光栅化会将其转换成屏幕上坐标,光栅化的处理不用关心
}
}%
CCProgram fs %{//标准结构,片元着色器
precision highp float;
in vec4 v_color;//vs传过来的顶点颜色
#if USE_TEXTURE
in vec2 v_uv0;//vs传过来的纹理坐标
uniform sampler2D mainTexture;//采样纹理
#endif
//uniform的另一种写法
uniform Constant {
vec4 mainColor;
};
//片元着色器的入口函数
vec4 frag () {
vec4 o = vec4(1,1,1,1);//定义的一个颜色 rgba;
#if USE_TEXTURE
o = texture(mainTexture,v_uv0);//纹理采样,获取texture指定的坐标(v_uv0)处的颜色保存到o中
#endif
o *= mainColor;//与纹理颜色混合
//指定当前片段(像素)的颜色值 o
return o;
//注意:片元着色器中必须返回一个四维颜色值,当片段着色器执行完毕后,o的值将被用来确定该片段最终显示的颜色。
//备注:为什么一张图片返回一个vec4就能显示图片的所有信息?
//实际上Shader是并行处理的,理论上gpu会给每一个顶点都使用这个shader,一张100*100的图片
//会有10000个shader在每一个像素并行处理
//总结新手常见出错:
//1.传参时类型不对,例如:vert输出时vec2,frag输入却是vec3或vec4
//2.自定义的参数没有在着色器中定义:如上Yaml中声明的mainColor参数在shader中需要定义:
// uniform Constant {
// vec4 mainColor;
// };
//3.使用内置函数或变量没有包含头文件
//4.Shader GLSL语句后一定要带分号
}
}%