当前位置:首页
> .html
导读:最近抖音上有个四分镜像的特效挺有意思,通过四分镜像一通乱画,能画出相当于窗花的效果。实现原理看着也比较简单,就随手实践下。
抖音四屏镜像摄像头的预览及四分屏效果参见OpenGL ...
最近抖音上有个四分镜像的特效挺有意思,通过四分镜像一通乱画,能画出相当于窗花的效果。实现原理看着也比较简单,就随手实践下。

抖音四屏镜像
摄像头的预览及四分屏效果参见OpenGL ES入门4-预览摄像头并叠加三角形
。其实原理很简单,只要对片元着色器进行处理就可以。
摄像头预览
android的后置相机的预览的图像是顺时针旋转90°的,而相对于前置相机则是逆时针旋转90°的

image.png
一般坐标是向右是X轴正向,向上是Y轴正向。对于纹理坐标,纹理的生成是由图片像素来生成的,而图像的存储是从左上角开始。所以一般理解纹理坐标X轴向右,Y轴向下。
顶点/纹理坐标及片元着色器代码
坐标代码:
// 顶点坐标
private float[] mPosCoordinate = {
-1, -1,
-1, 1,
1, -1,
1, 1};
// 纹理坐标
private float[] mTexCoordinate = {
1, 1,
0, 1,
1, 0,
0, 0};
因为后置摄像头预览的图像顺时针旋转90度,所以对应的顶点坐标和纹理坐标的对应关系要对应调整。
片元着色器代码:
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES videoTex;
varying vec2 textureCoordinate;
void main() {
vec2 uv = textureCoordinate;
if(uv.x <= 0.5 && uv.y >=0.5){ //左上
uv.x = (uv.x) * 2.0;
uv.y = (uv.y - 0.5) * 2.0;//左上方块整体沿y轴向右平移0.5,即可到达坐标原点
}
else if(uv.x <= 0.5 && uv.y <= 0.5){ //右上 - y轴镜像
uv.x = uv.x * 2.0;
uv.y = 1.0 - uv.y *2.0;
}
else if(uv.x >= 0.5 && uv.y >= 0.5){ // 左下 -x轴镜像
uv.x = 1.0-(uv.x - 0.5) * 2.0;
uv.y = (uv.y - 0.5) * 2.0;
}
else if(uv.x >=0.5 && uv.x <= 1.0 && uv.y <=0.5){ //右下 -x轴,y轴都做镜像
uv.x = 1.0-(uv.x-0.5) *2.0;
uv.y = 1.0-uv.y * 2.0;
}
vec4 tc = texture2D(videoTex, fract(uv));
gl_FragColor = vec4(tc.r,tc.g,tc.b,1.0);
}
如何理解主要原理呢?左上角是原图。主要原理如下:
1、放大处理。对于四分屏,原来顶点坐标对应的纹理坐标x,y要进行转换,如x<=0.5,y<=0.5的右上角区域要放大到0~1范围内。以左上角区域所示,放大原理如下:

image.png
先进行平移,移到右上角,然后x轴、y轴进行2倍放大。
2、镜像处理。
通过如下:
1.0 -(放大后的坐标值)
来取x轴的镜像坐标。其他情况的处理类似。
实际效果

四分镜像乱画.jpg
参考:
https://blog.csdn.net/zhangpengzp/article/details/89634640
发表评论: