OpenGLES(八)-GLSL案例:分屏滤镜原理OpenGLES(八)-GLSL案例:分屏滤镜原理

2021-08-09 11:19:01 浏览数 (1)

OpenGLES(八)-GLSL案例:分屏滤镜原理

效果图

本文中着重介绍glsl的分屏逻辑,对于iOS端的代码就省略了。如果对这部分有兴趣跳转OpenGLES(五)- ESLS案例:纹理贴图

顶点着色器

代码语言:javascript复制
attribute vec4 position;
attribute vec2 texCoord;
varying lowp vec2 varyTexCoord;

void main(void){
    gl_Position = position;
    varyTexCoord = texCoord;
}

片元着色器

对于分屏功能,最重要的就是顶点坐标和纹素的获取关系;也就是对于分屏滤镜算法的理解。

二分屏
  • 图中的数字都是纹理坐标
  • 左图中的红线代表了二分屏后的展示内容
  • 图中展示就是通过运算将原图中的纹理坐标,转换成目标图中的纹理坐标

认真观察两张图的坐标关系:

  1. 转换前原坐标(0.25,0),(0.75,0)-> 转换后纹理坐标(0,0),(0.5,0)
  2. 转换前(0.25,0),(0.75,0)-> 转换后(0.5,0),(1,0)
  3. 转换前(0.25,1),(0.75,1)-> 转换后(0,1),(0.5,1)
  4. 转换前(0.25,1),(0.75,1)-> 转换后(0.5,1),(1,1)

这种会涉及到一个简单的算法,具体看片元着色器中的处理:

代码语言:javascript复制
precision highp float;
varying lowp vec2 varyTexCoord;
uniform sampler2D colorMap;

void main(void){
    vec2 temp = varyTexCoord;
    if (temp.x <= 0.5) {
        temp.x = temp.x   0.25;
    }else{
        temp.x = temp.x - 0.25;
    }
    gl_FragColor = texture2D(colorMap, temp);
}

这里的计算不考虑顶点坐标,完全就是纹理坐标的映射关系。只需考虑在某一个纹理位置,你想要显示哪个坐标的纹素。

四分屏

因为4分屏中的每一部分都是完成的纹理图片,所以在计算上会略有不同。

坐标关系就不一一举例。

代码语言:javascript复制
precision highp float;
varying lowp vec2 varyTexCoord;
uniform sampler2D colorMap;

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

剩下的部分大同小异,都可以通过这种画图的方式来寻找思路,这里直接放出五分屏九分屏的代码。

五分屏
代码语言:javascript复制
precision highp float;
varying lowp vec2 varyTexCoord;
uniform sampler2D colorMap;

void main(void){
    vec2 temp = varyTexCoord;
    
    if(temp.x <= 0.5) {
        temp.x = temp.x * 2.0;
    }else{
        temp.x = (temp.x - 0.5) * 2.0;
    }
    if(temp.y <= 0.5) {
        temp.y = temp.y * 2.0;
    }else{
        temp.y = (temp.y - 0.5) * 2.0;
    }
    if((varyTexCoord.x >= 0.25 && varyTexCoord.x <= 0.75) && (varyTexCoord.y >= 0.25 && varyTexCoord.y <= 0.75)){
        temp = vec2((varyTexCoord.x - 0.25) * 2.0,(varyTexCoord.y - 0.25) * 2.0);
    }
    
    gl_FragColor = texture2D(colorMap, temp);
}
九分屏
代码语言:javascript复制
precision highp float;
varying lowp vec2 varyTexCoord;
uniform sampler2D colorMap;

void main(void){
    vec2 temp = varyTexCoord;
    
    if(temp.x <= 1.0 / 3.0){
        temp.x = temp.x   1.0 / 3.0;
    }else if(temp.x >= 2.0 / 3.0){
        temp.x = temp.x - 1.0 / 3.0;
    }
    
    if(temp.y <= 1.0 / 3.0){
        temp.y = temp.y   1.0 / 3.0;
    }else if(temp.y >= 2.0 / 3.0){
        temp.y = temp.y - 1.0 / 3.0;
    }
    
    gl_FragColor = texture2D(colorMap, temp);
}
总计

简单总结一下,想要完成这种类似的滤镜效果就是要通过观察找到变换的规律,然后通过对纹理坐标的计算来完成滤镜效果。个人理解就是:找到几个关键点,然后思考这些点具体需要展示的纹素是什么,从而完成计算.

完整DEMO地址: Github

0 人点赞