CocosCreator Shader学习(三):放大镜缩小镜效果

放大镜缩小镜效果

原理:根据缩放比例,判断镜面范围内的点实际应该显示哪个点的颜色值,问题就变成怎么根据缩放比例进行坐标转换!

顶点着色器代码不用修改。

片元着色器代码如下:

CCProgram fs %{
  precision highp float;
  
  #include <alpha-test>

  in vec4 v_color;

  #if USE_TEXTURE
  in vec2 v_uv0;
  uniform sampler2D texture;
  #endif

  uniform inputData{
    float scale; //缩放比例 0~1~2
    float showRadius; //显示半径
    vec2 imageSize; //图片实际尺寸
    vec2 point;  //缩放中心点
  };

  //检查pos点是否在显示圆内
  bool checkPointInCircle(vec2 pos){
    //pos是ndc坐标,转换成实际坐标
    pos.x *= imageSize.x;
    pos.y = (1.0 - pos.y)*imageSize.y;

    //计算pos到point的距离
    float distance = sqrt(pow(pos.x - point.x, 2.0) + pow(pos.y - point.y, 2.0));
    return distance <= showRadius;
  }
  //根据缩放比例转换坐标
  vec2 getPointTransition(vec2 pos){
    vec2 uv = vec2(point.x/imageSize.x, 1.0 - point.y/imageSize.y);
    uv.x = uv.x - (uv.x - pos.x)/scale;
    uv.y = uv.y - (uv.y - pos.y)/scale;
    return uv;
  }

  void main () {
    vec4 o = vec4(1, 1, 1, 1);
    #if USE_TEXTURE
      if(checkPointInCircle(v_uv0)){
        vec2 uv = getPointTransition(v_uv0);
        if(uv.x > 1.0 || uv.x < 0.0 || uv.y > 1.0 || uv.y < 0.0){
          //超出纹理范围的用黑色填充
          o = vec4(0, 0, 0, 1);
        }else{
          o *= texture(texture, uv);
          if(o.a == 0.0){
            //发现透明度为0的坐标,直接用黑色填充
            o = vec4(0, 0, 0, 1);
          }
        }
      }else{
        //不在圆内的点直接获取纹理
        o *= texture(texture, v_uv0);
      }
      #if CC_USE_ALPHA_ATLAS_TEXTURE
      o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;
      #endif
    #endif

    o *= v_color;

    ALPHA_TEST(o);

    gl_FragColor = o;
  }
}%

脚本代码如下:

const {ccclass, property} = cc._decorator;

@ccclass
export default class Cocos3 extends cc.Component {

    @property(cc.Label)
    label: cc.Label = null;

    @property(cc.Slider)
    slider: cc.Slider = null;

    material: cc.Material = null;
    scale: number = 1.0;

    start () {
        this.material = this.node.getComponent(cc.Sprite).getMaterial(0);
        //设置初始缩放比例
        this.material.setProperty("scale", this.scale);
        //设置缩放显示圆的半径
        this.material.setProperty("showRadius", 50.0);
        //设置图片宽高
        this.material.setProperty("imageSize", cc.v2(this.node.width, this.node.height));
        
        this.label.string = this.scale.toFixed(2);
        this.slider.progress = 0.5;
        this.slider.node.on("slide", this.sliderMoveCallBack, this);

        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.touchMoveCallBack, this);
    }

    // update (dt) {}

    private sliderMoveCallBack(slider: cc.Slider)
    {
        this.scale = slider.progress*1.9 + 0.1;
        this.label.string = this.scale.toFixed(2);
        //修改缩放比例
        this.material.setProperty("scale", this.scale);
    }

    private touchMoveCallBack(event: cc.Event.EventTouch){
        //当前获取到的触摸点是相对于左下角为原点的坐标,
        //需要经过一系列换算成相对于当前精灵左下角为原点的坐标。
        let pos: cc.Vec2 = event.getLocation();
        pos = pos.sub(cc.v2(cc.winSize.width/2, cc.winSize.height/2));
        pos = pos.sub(this.node.getPosition());
        pos = pos.add(cc.v2(this.node.getContentSize().width/2, this.node.getContentSize().height/2));
        
        //修改缩放中心点
        this.material.setProperty("point", pos);
    }
}

效果图如下:

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cocos Creator模拟砸金蛋3d旋转效果 | 附代码egg.zip // Learn TypeScript: // - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/typescript.html // - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/typescript.html // Learn Attribute: // - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html // - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/reference/attributes.html // Learn life-cycle callbacks: // - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html // - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/life-cycle-callbacks.html const {ccclass, property} = cc._decorator; @ccclass export default class Game extends cc.Component { @property Count: number = 5; @property(cc.Prefab) prefab: cc.Prefab = null; @property(cc.Node) nodeParent: cc.Node = null; private mEggs: cc.Node[] = []; // LIFE-CYCLE CALLBACKS: // onLoad () {} start () { } // update (dt) {} onClick(event, data){ switch(data){ case 'add':{ this.addEggs(); break; } case 'move':{ this.moveEggs(); break; } case 'stop':{ this.stopMoveEggs(); break; } } } addEggs(){ if(this.Count <= 0){ return; } this.mEggs = []; const N = 360 / this.Count; for(let i = 0; i < this.Count; i++){ let egg = cc.instantiate(this.prefab); let js = egg.getComponent('Egg'); js.setRadian(i * N * Math.PI / 180); js.updatePos(); egg.parent = this.nodeParent; this.mEggs.push(egg); } } moveEggs(){ for(let i = 0; i < this.mEggs.length; i++){ this.mEggs[i].getComponent('Egg').setMove(true); } } stopMoveEggs(){ for(let i = 0; i < this.mEggs.length; i++){ this.mEggs[i].getComponent('Egg').setMove(false); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值