creator shader:从零开始,扑克牌的透视效果

放下效果


很漂亮的透视啊,扑克牌完美嵌入桌面,甚至连牌面是几都看不出,但是我认识J那张画hh

顶点着色器

老规矩,新建一个effect,啥也别改,这次我们要做顶点变换,先看一下新建出来的干净的顶点着色器代码,

2d用的啥模型我不知道,目前看效果应该就是两个三角面片,四个顶点。片元着色器对四个顶点执行计算

CCProgram vs %{
  precision highp float;

  #include <cc-global>
  #include <cc-local>

  in vec3 a_position;
  in vec4 a_color;
  out vec4 v_color;

  #if USE_TEXTURE
  in vec2 a_uv0;
  out vec2 v_uv0;
  #endif

  void main () {
    vec4 pos = vec4(a_position, 1);


    // 下面的代码基本都不敢动,我们只修改上面
    // 模型的顶点变换 不敢动!
    #if CC_USE_MODEL
    pos = cc_matViewProj * cc_matWorld * pos;
    #else
    pos = cc_matViewProj * pos;
    #endif

    // 给片元着色器传值 v_uv0 不敢动!
    #if USE_TEXTURE
    v_uv0 = a_uv0;
    #endif

    // 给片元着色器传值 v_color 不敢动! 这个v_color就是在sprite组件里能调整的颜色的值
    v_color = a_color;

    // 输出的最终坐标。
    gl_Position = pos;
  }
}%

想要达到效果,其实修改就是扑克牌上边缘两个顶点的x轴坐标

但是想要修改,最起码知道现在的值是多少吧,做个测试看一下。
让顶点坐标的x值 += y值 观察x坐标的变化规律

void main () {
    vec4 pos = vec4(a_position, 1);
    pos.x += pos.y;

在这里插入图片描述
可以看到,蓝色线框是牌原本的边框,底边的x轴没有变化,所以底边的 += pos.y 这里的y值是0

在这里插入图片描述

调整一下位置,牌的左上角顶点和画布左上角顶点重合时,上边两个顶点的值往右偏了 屏幕高度那么多的值。 看一下蓝框很直观,正方形嘛,偏移宽度=屏幕高度

这说明顶点在画布上边缘位置时,顶点坐标y值是画布高

这里测试了x,y也是一样,其实偏远着色器中我们拿到的a_position就是一个 屏幕左下角 (0,0) -> 屏幕右上角 (画布宽,画布高)这样的vec2变量,有了顶点的具体值,后面就好操作了。
画一下顶点的屏幕坐标


很明显,这就是世界坐标。。2d的shader可能是已经把模型局部坐标转换过世界坐标才传进来的,但是无所谓了,我们做变换够用了。

顶部偏移

咋偏移呢,

我来定一个顶点point ,我要让所有的扑克往这个点变形。
设点point 坐标vec2(屏幕宽/2,屏幕高*0.85)

对每个点来说,点的x轴偏移值 = `(顶点x和pointx差值)* (顶点y和point.y的比例),

    vec2 point = vec2(1920. * .5,1080. * 0.85);
    pos.x += (point.x - pos.x) * (pos.y / point.y);

在这里插入图片描述

看一下

在这里插入图片描述
很明显啊,所有的扑克都已经在预想的轨迹上变化了。

修改起点y值

有个问题,就是这里的计算 都是用屏幕底边y值0计算的,我牌桌变如果不在屏幕底边咋办呢,我要指定一个起点的y值可以计算这个三角形。

比如我牌摆在离底边100px的位置,
在这里插入图片描述
扑克明显变小了,我要这样的
在这里插入图片描述

其实简单,参与计算的y坐标 减100就行了。

pos.x += (point.x - pos.x) * ((pos.y - 100.) / point.y);

放一下最终代码,让起点y值和终点坐标都用可变变量,从材质传值进来。

// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.  

CCEffect %{
  techniques:
  - passes:
    - vert: vs
      frag: fs
      blendState:
        targets:
        - blend: true
      rasterizerState:
        cullMode: none
      properties:
        texture: { value: white }
        u_point: { value: [1,1] }
        u_starty: {value: 0 }
        alphaThreshold: { value: 0.5 }
}%


CCProgram vs %{
  precision highp float;

  #include <cc-global>
  #include <cc-local>

  in vec3 a_position;
  in vec4 a_color;
  out vec4 v_color;

  #if USE_TEXTURE
  in vec2 a_uv0;
  out vec2 v_uv0;
  #endif

  uniform Constant{
    vec2 u_point;
    float u_starty;
  };

  void main () {
    vec4 pos = vec4(a_position, 1);
    
    pos.x += (u_point.x - pos.x) * ((pos.y - u_starty) / u_point.y);

    
    // 下面的代码基本都不敢动,我们只修改上面
    // 模型的顶点变换 不敢动!
    #if CC_USE_MODEL
    pos = cc_matViewProj * cc_matWorld * pos;
    #else
    pos = cc_matViewProj * pos;
    #endif

    // 给片元着色器传值 v_uv0 不敢动!
    #if USE_TEXTURE
    v_uv0 = a_uv0;
    #endif

    // 给片元着色器传值 v_color 不敢动! 这个v_color就是在sprite组件里能调整的颜色的值
    v_color = a_color;

    // 输出的最终坐标。
    gl_Position = pos;
  }
}%


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

  in vec4 v_color;

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

  void main () {
    vec4 o = vec4(1, 1, 1, 1);

    #if USE_TEXTURE
      CCTexture(texture, v_uv0, o);
    #endif

    o *= v_color;

    ALPHA_TEST(o);

    gl_FragColor = o;
  }
}%

需要不同透视角度,只需要调整顶点值的位置就好了。


贴一下公众号
image

26赞

好东西,收藏了

写作不易,感谢分享!!!

mark!

牛啤哄哄收藏了

大佬这个变形了会不会有很严重的锯齿

有的,还没找到解决方案。

glEnable(GL_LINE_SMOOTH);//启用线段平滑

glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // 设置线段平滑程度

glLineWidth(6);

上面的好像可以搞搞试试,但是不知道creator怎么调这几个接口,论坛搜了一圈,全都是说1.8以后弃用了,都在找怎么调用 :upside_down_face:

有点高深,我摸索摸索,我这是透视相机照出来的图片变形了,会有锯齿


不是相机的问题 斜边都有这问题

:joy:感觉没有好的解决方案,只能反抗项目经理改需求了

cycycycycycy…

又到了抄作业的时刻了 :rofl:

mark~

诶呦不错哦

mark :smiley: :smiley:

mark!

mark!

https://gitee.com/yeshao2069/cocos-creator-shader/tree/v3.5.x/demo/2dP1/Creator3.5.2_2D_CardPerspective

升级3.5.2 参考

shaderTest
:upside_down_face:我怎么感觉这好像直接扭曲了。。。