空无以求全
宁静以致远
当前位置:首页 > .html

OpenGL ES 仿抖音四屏镜像乱画

作者:大熊空间发布时间:2022-02-19 17:09分类: 浏览:227评论:0


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


发表评论: