镜像着色器和分镜着色器

1,104 阅读2分钟

左半边镜像着色器

左半边镜像效果

镜像效果

#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);
}

四分镜着色器

四分镜效果

image.png

#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,正好满足我们的对称的特点。
image.png

四分镜原理

图像分别在左上,左下,右上,右下显示的整个视频画面。比如左上举例:就是当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出来看,他具有如下的函数特性:

image.png

在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分镜

image.png

#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]区间内

image.png

50*50分镜

image.png