左半边镜像着色器
左半边镜像效果
#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision highp float;
in vec2 texCoo2Frag;
out vec4 outColor;
layout (location = 4) uniform samplerExternalOES sTexture;
void main() {
vec2 pos = texCoo2Frag;
pos.x = min(pos.x,1.0-pos.x);
outColor = texture(sTexture, pos);
}
四分镜着色器
四分镜效果
#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision highp float;
in vec2 texCoo2Frag;
out vec4 outColor;
uniform samplerExternalOES sTexture;
void main(){
vec2 pos = texCoo2Frag.xy;
pos = vec2(2.0*pos.x-step(0.5,pos.x),2.0*pos.y-step(0.5,pos.y));
outColor = texture(sTexture, pos);
}
左半边镜像原理
图像的左半边正常显示视频左边的纹理,右边显示左半边的对称纹理。
对于纹理的取值在函数上有这样的特性:
y = min(x,1-x)
可以清楚的发现,在x<0.5的时候,函数返回x,在x>0.5的时候,函数返回1.0-x,正好满足我们的对称的特点。
四分镜原理
图像分别在左上,左下,右上,右下显示的整个视频画面。比如左上举例:就是当x<0.5,y<0.5的时候,映射到视频纹理中的[0,1]归一化区间去就可。右上,x∈[0.5,1],y∈[0,0.5],那么也要对应到视频纹理的[0,1]区间去。左下,x∈[0,0.5],y∈[0.5,1],也是同理。
单纯拎一个x出来看,他具有如下的函数特性:
在0-0.5区间:y = 2.0 * x
在0.5-1区间:y = 2.0 * x - 1.0
而这,恰好使用2.0*x - step(0.5,x)来表示。
y分量上也是同理的。
书接上文
有的朋友就说了,你这四分镜也不对啊,你这只能是四分镜,人家虽然走的是if,else,可人家稍微修改一下,同样的道理,也能做2分镜,3分镜,6分镜,8分镜啊。你这也不通用啊!
确实,我的四分镜只能是四分镜。没办法做8分镜,16分镜,等等等等。
但是原理是一样的,我只需要稍稍修改一下我的函数即可。
N分镜
#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision highp float;
in vec2 texCoo2Frag;
out vec4 outColor;
uniform samplerExternalOES sTexture;
#define PI 3.1415926
float tri(float x){
return abs(sign(sin(PI*x)))*fract(x);
}
#define N_POINTS 4.0
void main(){
vec2 pos = texCoo2Frag.xy;
pos.x = tri(N_POINTS*pos.x);
pos.y= tri(N_POINTS*pos.y);
outColor = texture(sTexture, pos);
}
//N分镜的三角波的另一种写法,取余后归一化
#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision highp float;
in vec2 texCoo2Frag;
out vec4 outColor;
uniform samplerExternalOES sTexture;
#define PI 3.1415926
#define N_POINTS 8.0
float tri(float x){
return mod(x,1.0/N_POINTS)*N_POINTS;
}
void main(){
vec2 pos = texCoo2Frag.xy;
pos.x = tri(pos.x);
pos.y= tri(pos.y);
outColor = texture(sTexture, pos);
}
N分镜函数
和四分镜原理相同,只是tri函数是一个锯齿波,在[0,1]区间内