1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > Cocos Creator Shader实现镂空遮罩

Cocos Creator Shader实现镂空遮罩

时间:2022-11-07 23:57:03

相关推荐

Cocos Creator Shader实现镂空遮罩

Cocos Creator Shader实现镂空遮罩

前言

想不到距离上一遍博客更新已经有13个月之久了,之前定下的一个月至少更新一遍早已不知什么时候抛之脑后。今天开个头,希望以后输出更多的学习总结。

该文起源是同事的一个需求,实现一个简单的镂空遮罩引导,具体效果如下

实现思路

看到这个第一个感觉应该是使用cocos shader,在指定区域做一个镂空处理,需要变化的参数就是指定位置position,镂空尺寸。黑幕渐变的效果就是宽高递减,在ts上根据指定速度递减。

编写shader

下面我们先来实现shader,话不多说,直接上代码

CCEffect %{techniques:- passes:- vert: vsfrag: fsblendState:targets:- blend: truerasterizerState:cullMode: noneproperties:size: { value: [1920.0, 1080.0], editor: { tooltip: '节点尺寸' } }center: { value: [0.5, 0.5], editor: { tooltip: '中心点 (左上角为原点)' } }width: { value: 0.5, editor: { tooltip: '宽 (目标宽度 / 节点宽度)' } }height: { value: 0.5, editor: { tooltip: '高 (目标高度 / 节点宽度)' } }}%CCProgram vs %{precision highp float;#include <cc-global>in vec3 a_position;in vec2 a_uv0;in vec4 a_color;out vec2 v_uv0;out vec4 v_color;void main () {gl_Position = cc_matViewProj * vec4(a_position, 1);v_uv0 = a_uv0;v_color = a_color;}}%CCProgram fs %{precision highp float;in vec2 v_uv0;in vec4 v_color;uniform sampler2D texture;uniform Properties {vec2 center;vec2 size;float width;float height;};void main () {vec4 color = v_color;color *= texture(texture, v_uv0);// 边缘float ratio = size.x / size.y;float minX = center.x - (width / 2.0);float maxX = center.x + (width / 2.0);float minY = center.y - (height * ratio / 2.0);float maxY = center.y + (height * ratio / 2.0);if (v_uv0.x >= minX && v_uv0.x <= maxX && v_uv0.y >= minY && v_uv0.y <= maxY) {// 下面判断4个边,和中间位置vec2 vertex;if (v_uv0.x <= minX) {vertex=vec2(minX,v_uv0.y/ratio);} else if (v_uv0.x >= maxX) {vertex=vec2(maxX,v_uv0.y/ratio);} else if (v_uv0.y <= minY) {vertex = vec2(v_uv0.x, minY/ ratio); // 上} else if (v_uv0.y >= maxY) {vertex = vec2(v_uv0.x,maxY/ ratio); // 下} else {discard; // 中间discard表示直接丢弃,不渲染}float dis = distance(vec2(v_uv0.x, v_uv0.y / ratio), vertex);}color.a *= v_color.a;gl_FragColor = color;}}%

代码很少,就几行,如果不理解的可以翻看我之前几遍shader的文章应该可以懂得。

编写ts更改相应参数

核心shader完成,接下来要做的就是通过获取到这个shader然后通过改变其参数来移动定位到具体镂空位置。这里我这里一个范例,可以直接拿来用。

const {ccclass, property} = cc._decorator;/*** * 把这个类挂在一个遮罩的Sprite里,这个Sprite节点一般是一个黑色的图,透明度直接在color上设置就好*/@ccclassexport default class GuideShader extends ponent {/** 这里实现点击某个节点,获取鼠标位置,定位到这里 */@property(cc.Node)clickTarget:cc.Node=null;/** 黑幕遮罩移动的速度 */@propertypublic wSpeed:number=90;@propertypublic hSpeed:number=70;private shader:cc.MaterialVariant=null;/** 镂空的宽高 */private btnWh:cc.Vec2=cc.v2(160,80);private isUpdate:boolean=false;/** 这里一般为屏幕尺寸 */private widthDiff=1920;private heightDiff=1080;onLoad () {this.node.width=cc.winSize.width;this.node.height=cc.winSize.height;}start () {this.shader=this.node.getComponent(cc.Sprite).getMaterials()[0];this.clickTarget && this.clickTarget.on(cc.Node.EventType.TOUCH_END,this.clickHandle,this);}private clickHandle(e:cc.Event.EventTouch){this.setLocation(e.getLocation(),this.btnWh);}public setLocation(location:cc.Vec2,focusWH:cc.Vec2){/** 设置相应的shader属性 */this.shader.setProperty('center',cc.v2(location.x/cc.winSize.width,1-location.y/cc.winSize.height));this.widthDiff=cc.winSize.width;this.heightDiff=cc.winSize.height;this.btnWh=focusWH;this.isUpdate=true;}update (dt) {if(this.isUpdate){if(this.widthDiff>this.btnWh.x) this.shader.setProperty('width',this.widthDiff/cc.winSize.width);else this.shader.setProperty('width',this.btnWh.x/cc.winSize.height);if(this.heightDiff>this.btnWh.y) this.shader.setProperty('height',this.heightDiff/cc.winSize.height);else this.shader.setProperty('height',this.btnWh.y/cc.winSize.height);this.widthDiff-=this.wSpeed;this.heightDiff-=this.hSpeed;}}}

这样就能实现上面gif的效果了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。