放下效果
很漂亮的透视啊,扑克牌完美嵌入桌面,甚至连牌面是几都看不出,但是我认识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;
}
}%
需要不同透视角度,只需要调整顶点值的位置就好了。
贴一下公众号