//扫光-纹理 CCEffect %{ techniques: - passes: - vert: vs frag: fs blendState: targets: - blend: true rasterizerState: cullMode: none properties: texture: { value: white } u_fluxayTexture: { value: white } u_time: { value: 0 } u_scale: { value: 1.0 } u_angle: { value: 30.0 } u_uvRotated: { value: 0.0 } u_uvOffset: { value: [0.0,0.0,1.0,1.0] } }% // Vertex Shader(顶点着色器) // 将顶点从模型空间坐标系统转化到屏幕空间坐标系统 // 顶点着色器分为输入和输出两部分 // 负责的功能是把输入的数据进行矩阵变换位置,计算光照公式生成逐顶点颜⾊,⽣成/变换纹理坐标 // 并且把位置和纹理坐标这样的参数发送到片段着色器 CCProgram vs %{ precision highp float; #include #include // 输入的顶点坐标 in vec3 a_position; // 输入的顶点颜色 in vec4 a_color; // 输出的顶点颜色 out vec4 v_color; #if USE_TEXTURE // 输入的纹理坐标 // UV坐标:原点在左上角,u轴是向右,v轴是向下,范围是0-1 in vec2 a_uv0; // 输出的纹理坐标 out vec2 v_uv0; #endif void main () { mat4 mvp; #if CC_USE_MODEL mvp = cc_matViewProj * cc_matWorld; #else mvp = cc_matViewProj; #endif v_uv0 = a_uv0; v_color = a_color; gl_Position = mvp * vec4(a_position, 1); } }% // Fragment Shader(片段着色器) // 片元着色器的作用是处理由光栅化阶段生成的每个片元,最终计算出每个像素的最终颜色(RGBA) CCProgram fs %{ precision highp float; #include #include in vec4 v_color; in vec2 v_uv0; uniform sampler2D texture; uniform sampler2D u_fluxayTexture; //流光纹理 // 自定义属性 // 所有非 sampler 的 uniform 都必须以 UBO 形式声明 // UBO 成员声明类型和顺序有严格的校验机制,以排除 GL 标准下隐式布局对齐带来的内存消耗 // u_uvRotated图片是否旋转 // u_uvOffset 图片minx,miny,maxx,maxy uniform ARGS { float u_time; float u_scale; float u_angle; float u_uvRotated; vec4 u_uvOffset; }; vec2 transformUV(vec2 UV,float angle){ float rotate = (angle * 3.1415926) / 180.0; vec2 di = vec2(0.5, 0.5); // 旋转的中心位置 //float a = cos(rotate); mat3 m = mat3(cos(rotate), -sin(rotate), 0.0,sin(rotate), cos(rotate), 0.0,0.0, 0.0, 1.0); //vec3 uv = vec3(UV.x-di.x,UV.y+di.y, 1.0)* m; //return vec2(uv.x,uv.y)+vec2(di.x,-di.y); vec3 uv = vec3(UV.x,UV.y, 1.0)* m; return vec2(uv.x,uv.y); } void main () { vec4 o = vec4(1, 1, 1, 1); #if USE_TEXTURE // texture.inc 核心函数 // o = texture2D(texture, v_uv0); // texture: 纹理,v_uv0: 纹理坐标,通过 GLSL 的内建函数 texture2D 来获取纹理上对应UV坐标的颜色(RGBA) o = texture2D(texture, v_uv0); #endif // 纹理颜色和顶点颜色(节点颜色)叠加得到最终颜色 o *= v_color; // alpha-test.inc 核心函数 // if (color.a < alphaThreshold) discard; // discard:退出片段着色器,不执行后面的片段着色操作,片段也不会写入帧缓冲区 ALPHA_TEST(o); //纹理的xMin float xMin = u_uvOffset.x; float xWidth = u_uvOffset.z - u_uvOffset.x; //x 转换成扫光图片上的位置 float x = (v_uv0.x - xMin)/xWidth; float yMin = u_uvOffset.y; float yWidth = u_uvOffset.w- u_uvOffset.y; //y 转换成扫光图片上的位置 float y = (v_uv0.y - yMin)/yWidth; float angle = u_angle; if(u_uvRotated >= 1.0) { x = (v_uv0.y - yMin)/yWidth; y = (v_uv0.x - xMin)/xWidth; angle = -u_angle; } // 在底图不透明的地方叠加流光纹理的颜色 if(o.a >= 1.0) { // 根据时间设置流光纹理的UV vec2 fluxayUV = vec2(x, y); x += u_scale; float time = u_time*(1.0+u_scale); //if(fluxayUV.x > u_time-u_scale && fluxayUV.x = 1.0) { // 获取流光纹理上UV的颜色 fluxayUV.x = (x-time)/ u_scale; fluxayUV = transformUV(fluxayUV,angle); vec4 fluxay = texture2D(u_fluxayTexture, fluxayUV); o.a = fluxay.a; // 叠加颜色 gl_FragColor = o; } else { o.a = 0.0; gl_FragColor = o; } } else { o.a = 0.0; gl_FragColor = o; } } }%