iOS视觉-- (08) OpenGL ES+GLSL实现分屏滤镜解析

通过前一篇我们学习了图片灰色滤镜,上一篇图片多滤镜。滤镜的实现其实就是对着色器进行编程,把渲染管线封装好,替换着色器就可以了。

少废话,先看效果Demo

  • 二分屏

二分屏效果图
注意⚠️:着色器中最好不要写中文注释,有可能编译不成功,这里主要是为了便于理解
  • 左右二分屏着色器代码:
precision mediump float; //通过precision关键字来指定默认精度,这样就不用每一个变量前面都声明精度限定符了

varying lowp vec2 varyTextCoord; //顶点着色器传递过来的纹理坐标

uniform sampler2D colorMap; //纹理

void main()
{
    //利用一个临时的二维向量,获取到纹理坐标
    vec2 uv = varyTextCoord.xy;
    float x;
    if (uv.x >= 0.0 && uv.x <= 0.5) {
        // 将x坐标的值映射为0.25~0.75
        x = uv.x + 0.25;
    } else {
        x = uv.x - 0.25;
    }
    //获取纹素
    gl_FragColor = texture2D(colorMap, vec2(x, uv.y));
    //由于y的值没有变,不需要再设y的值
}

分析:原理:1.先找到显示范围 --->2.确定映射关系
通过前面的学习,我们知道纹理左边是由左下角(0,0)到右上角(1,1),构成的,如下图:

纹理坐标

1.先找到显示范围:人物大概在0.25~0.75的位置,所以映射时就从纹理X轴的0.25位置开始,到0.75结束,如下图:
纹理映射图

2.确定映射关系
所以左边屏幕就是:x = uv.x + 0.25;
那么右边的屏幕就是:x = uv.x - 0.25;(意思就是:右边屏幕也要映射纹理0.25~0.75)
这里刚好是4份,比较特殊;

比方说:如果需要显示的区域从左边的风车开始,大约就是0.1,那么加上屏幕的一半(0.5),最大的X轴就是0.6。
所以左边屏幕就是:x = uv.x + 0.1;
那么右边的屏幕就是:x = uv.x - 0.4;

效果图

那么上下二分屏大家应该也知道怎么算了。人脸的范围大概在Y轴的(0.45~0.95),如下图


上下二分屏图
  • 上下二分屏着色器代码:
void main()
 {
     //利用一个临时的二维向量,获取到纹理坐标
     vec2 uv = varyTextCoord.xy;
     float y;
     if (uv.y >= 0.0 && uv.y <= 0.5) {
         // 将Y坐标的值映射为0.45~0.95
         y = uv.y + 0.45;
     } else {
         y = uv.y - 0.05;
     }
     //获取纹素
     gl_FragColor = texture2D(colorMap, vec2(uv.x, y));
     //由于X的值没有变,不需要再设y的值
 }

  • 三分屏

上面学习了二分屏,那么三分屏也是这样的,过程就不解析了。把屏幕分成三份,找到显示范围,确定映射关系就OK了。

  • 三分屏着色器代码:
precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;

void main() {
    vec2 uv = varyTextCoord.xy;
    if (uv.y >= 0.0 && uv.y < 1.0/3.0) {
        //下边
        uv.y = uv.y + 2.0/3.0 - 0.05;
    } else if(uv.y >2.0/3.0){
        //上边
        uv.y = uv.y - 0.05;
    } else {
        //中间
        uv.y = uv.y + 1.0/3.0 - 0.05;
    }
    gl_FragColor = texture2D(colorMap, uv);
}

  • 四分屏

四分屏

本来这块正方形是显示一张图片,现在感觉是显示了4张图片,就好像是把纹理缩小到四分之一的大小

  • 四分屏片元着色器代码:
precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;

void main(){
    vec2 uv = varyTextCoord.xy;
    if (uv.x <= 0.5) {
        uv.x = uv.x * 2.0;
    } else {
        uv.x = (uv.x - 0.5) * 2.0;
    }
    
    if (uv.y <= 0.5) {
        uv.y = uv.y * 2.0;
    } else {
        uv.y = (uv.y - 0.5) * 2.0;
    }
    gl_FragColor = texture2D(colorMap, uv);
}

代码中的意思就是X轴,Y轴各缩小2倍。有的同学肯定会问,为什么是乘以2呢?不应该是除以2吗?我们把上面的代码通过临时变量来看就比较清楚一点,如下

precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;

void main(){
    vec2 uv = varyTextCoord.xy;
    float a; //新的纹理坐标X值
    float b = uv.x; //原来的纹理坐标X值
    if (b <= 0.5) {
        a = b * 2.0;
    } else {
        a = (b - 0.5) * 2.0;
    }
    uv.x = a;
    
    if (uv.y <= 0.5) {
        uv.y = uv.y * 2.0;
    } else {
        uv.y = (uv.y - 0.5) * 2.0;
    }
    gl_FragColor = texture2D(colorMap, uv);
}

因为我们要屏幕的一半显示完X轴、Y轴,设纹理X轴为b,Y轴为A,那么关系就如图下所示:


四分屏

六分屏和九分屏原理和四分屏类似,只贴代码

  • 六分屏

precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;

void main(){
    vec2 uv = varyTextCoord.xy;
    if (uv.x <= 0.5) {
        uv.x = uv.x * 2.0;
    } else {
        uv.x = (uv.x - 0.5) * 2.0;
    }
    
    if (uv.y <= 1.0/3.0) {
        uv.y = uv.y * 3.0;
    } else if(uv.y > 1.0/3.0 && uv.y <= 2.0/3.0) {
        uv.y = (uv.y - 1.0/3.0) * 3.0;
    }else{
        uv.y = (uv.y - 2.0/3.0) * 3.0;
    }

    gl_FragColor = texture2D(colorMap, uv);
}


  • 九分屏

precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;

void main(){
    vec2 uv = varyTextCoord.xy;
    if (uv.x <= 1.0/3.0) {
        uv.x = uv.x * 3.0;
    } else if(uv.x > 1.0/3.0 && uv.x <= 2.0/3.0) {
        uv.x = (uv.x - 1.0/3.0) * 3.0;
    }else{
        uv.x = (uv.x - 2.0/3.0) * 3.0;
    }
    
    if (uv.y <= 1.0/3.0) {
        uv.y = uv.y * 3.0;
    } else if(uv.y > 1.0/3.0 && uv.y <= 2.0/3.0) {
        uv.y = (uv.y - 1.0/3.0) * 3.0;
    }else{
        uv.y = (uv.y - 2.0/3.0) * 3.0;
    }
    gl_FragColor = texture2D(colorMap, uv);
}

你可能感兴趣的:(iOS视觉-- (08) OpenGL ES+GLSL实现分屏滤镜解析)