Loading...
墨滴

四五戒

2021/08/26  阅读:53  主题:默认主题

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;
}
}%

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

四五戒

2021/08/26  阅读:53  主题:默认主题

作者介绍

四五戒