Cocos effect基本知识
注:此处所说Cocos creator版本为3.X,和其他版本会有区别。
Cocos effect是基于opengl的,使用glsl语法和函数。但是经过了cocos进行封装,所以一般看不到main函数,直接写关键函数即可。点击写好的effect,在Cocos creator属性面板可以看到生成的完整代码。
effect一般会有三个部分:
- CCEffect 声明部分
- CCProgram vs 顶点着色器
- CCProgram fs 片段着色器
CCEffect中每个passes都需要指定顶点着色器和片段着色器,一般都是vs:vert
和fs:frag
两个函数。而CCProgram就是具体实现了。
声明部分可以参考官方文档,这部分文档还算全面,在此就不再赘述。下面主要介绍顶点着色器。
顶点着色器有2个参数,a_position
和a_color
。如果有纹理的话,还会多个a_texCoord
参数。a_position
是世界坐标,a_color
是设定的渲染颜色(如果是sprite,可以看到属性面板有个color属性,就是这个),a_texCoord
是当前点对应纹理的位置。
一般来说,世界坐标是无法直接使用的,需要转换成视图投影(你可以理解成,世界坐标需要转换成摄像头坐标,摄像头坐标的(0,0)代表屏幕中间。ccc是这么定的。)我们需要引用#include <cc-global>
,得到视图投影矩阵cc_matViewProj
,返回cc_matViewProj * pos
即可完成顶点着色器。
注意:这是2D情况,3D还需要引用#include <cc-local>
得到模型空间转世界空间矩阵cc_matWorld
,再乘以这个。而2D情况下不能引用这个文件,否则会报错。
片段着色器是核心部分,一般要做什么效果都要在这里写。如果只是单纯的显示图片,return texture(cc_spriteTexture, uv);
即可。texture函数会把图片当前位置的颜色返回出来,提供给片段着色器完成渲染。其他更复杂的处理就看后续学习了。
下面是基于 陈皮皮写的某个effect进行适配的示例,原始文件在这里
CCEffect %{
techniques:
- passes:
- vert: vs:vert
frag: fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
blendDstAlpha: one_minus_src_alpha
rasterizerState:
cullMode: none
properties:
center: { value: [0.5, 0.5], editor: { tooltip: '模糊中心点' } }
strength: { value: 0.03, editor: { tooltip: '模糊强度' } }
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
in vec3 a_position;
in vec2 a_texCoord;
in vec4 a_color;
out vec2 v_uv0;
vec4 vert () {
vec4 pos = vec4(a_position, 1);
pos = cc_matViewProj * pos;
v_uv0 = a_texCoord;
return pos;
}
}%
CCProgram fs %{
precision highp float;
in vec2 v_uv0;
#pragma builtin(local)
layout(set = 2, binding = 10) uniform sampler2D cc_spriteTexture;
//定义文件里写的属性可以这样获取
uniform Properties {
vec2 center;
float strength;
};
// 获取径向模糊颜色
vec4 getRadialBlurColor(vec2 coord) {
// 偏移
vec2 offset = coord.xy - center;
// 采样次数
const int samples = 10;
// 强度
float perStrength = strength / float(samples - 1);
// 采样
vec4 color = vec4(0.0);
for(int i = 0; i < samples; i++) {
vec2 uv = offset * (1.0 + (float(i) * perStrength)) + center;
color += texture(cc_spriteTexture, uv);
}
color /= float(samples);
// 完成
return color;
}
vec4 frag () {
vec4 o = vec4(1, 1, 1, 1);
o *= getRadialBlurColor(v_uv0);
return o;
}
}%