OpenGLES:相机实时滤镜四宫格、九宫格

  • Post author:
  • Post category:其他


一.概述

今天继续OpenGLES的学习

今天在之前博文

《OpenGLES:GLSurfaceView实现Android Camera预览》

的基础上,使用OpenGLES实现相机

四宫格滤镜



九宫格滤镜

二.四宫格

先定义几个名词:

  • 之前博文中实现的相机普通预览叫:

    “大宫格”
  • 现在要实现的是:”

    四宫格”+”滤镜”
  • 四宫格的每一个小宫格叫:

    “小宫格”
  • 小宫格区域内的点记为:

    (min_x, min_y)
  • 小宫格原点记为:

    (min_origin_x, min_origin_y)
  • 大宫格区域内的点记为:

    (max_x, max_y)


大宫格原点是(0,0)

,不用专门标记

先看怎么实现

四宫格

,再看怎样

+滤镜


小宫格

(min_x, min_y)是从属于

大宫格

(max_x, max_y)的,它只是(max_x, max_y)的一个

1/4子区域


我们要做的就是怎么把(min_x, min_y)通过换算对应到(max_x, max_y)

通过图示不难看出:

1.

大宫格

相当于

小宫格

沿x、y轴反方向移动(min_origin_x, min_origin_y)到(0,,0),再将长、宽乘以2



也可以反向认为:



2.

小宫格

相当于

大宫格

的长、宽都除以2,再沿x、y轴正向移动到(min_origin_x,min_origin_y)



“右上角小宫格”




例:

1.

大宫格

相当于

右上角小宫格


沿x,y轴反方向移动(0.5,0.5)到(0,0),再将长、宽都放大2倍



或者

2.

右上角小宫格

相当于

大宫格

长、宽都缩小1/2,再沿x、y轴正方向移动到(0.5,0.5)

我们要做的是怎么把纹理采样坐标中的

部分坐标

(

小宫格

)对应到

全部坐标

(

大宫格

)

所以我们要找到的是上述

“1.”

的对应关系,反向的

“2.”

是为了更形象的理解过程

按照这种方法,不管多复杂的宫格分割,只要推导出

小宫格

通过怎样的

平移和缩放

能够与

“大宫格”

重叠,就能找到对应关系

所以

“小宫格”

换算对应到

“大宫格”

的公式:

max_x = (min_x – min_origin_x) *2

max_y = (min_y – min_origin_y) *2

(min_origin_x, min_origin_y)可以再进一步通过要实现的

“几宫格”



“几”

进行公式化,这个不难,就不推导了。

三.滤镜

在片段着色器中,通过

纹理采样器



纹理坐标

创建出

纹理

创建的纹理其实就是要赋值给内建变量的

颜色值向量

这也是为什么要通过

纹理采样器



纹理坐标

,相当于纹理采样器根据纹理坐标获取这个坐标点的颜色值,所有颜色值形成一张五彩缤纷的图,就是

纹理

通过颜色向量可以拿到色值的

RGB分量

那么就可以对颜色做出各种

“滤镜”

效果了

如下是

黑白

滤镜代码:

//黑白
void blackAndWhite(inout vec4 color){
    float threshold = 0.5;
    float mean = (color.r + color.g + color.b) / 3.0;
    color.r = color.g = color.b = mean >= threshold ? 1.0 : 0.0;
}

直接通过代码字面就能理解了:

纹理坐标点采样到的颜色值的(r、g、b)三个分量,如果平均值>0.5,就赋值为白,反之为黑。

如下就是最终实现四宫格的

黑白、灰度、反向、原图

实时滤镜着色器代码:

看字面都很好理解,不一一说明了

#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision mediump float;

in vec2 texCoord;//纹理坐标,图片当中的坐标点
out vec4 outColor;

uniform samplerExternalOES s_texture;//图片,采样器

//黑白
void blackAndWhite(inout vec4 color){
    float threshold = 0.5;
    float mean = (color.r + color.g + color.b) / 3.0;
    color.r = color.g = color.b = mean >= threshold ? 1.0 : 0.0;
}

//灰度
void grey(inout vec4 color){
    float weightMean = color.r * 0.3 + color.g * 0.59 + color.b * 0.11;
    color.r = color.g = color.b = weightMean;
}

//反向
void reverse(inout vec4 color){
    color.r = 1.0 - color.r;
    color.g = 1.0 - color.g;
    color.b = 1.0 - color.b;
}

void main(){
    float x = texCoord.x;
    float y = texCoord.y;

    //四宫格滤镜
    if (x <= 0.5 && y <= 0.5){
        x = x * 2.0;
        y = y * 2.0;
        outColor = texture(s_texture, vec2(x, y));
        reverse(outColor);
    } else if (x <= 0.5 && y >= 0.5){
        x = x * 2.0;
        y = (y-0.5) * 2.0;
        outColor = texture(s_texture, vec2(x, y));
        blackAndWhite(outColor);
    } else if (x>0.5 &&  y > 0.5){
        x = (x-0.5) * 2.0;
        y = (y-0.5) * 2.0;
        outColor = texture(s_texture, vec2(x, y));
        grey(outColor);
    } else if (x>0.5 &&  y < 0.5){
        x = (x-0.5) * 2.0;
        y = y * 2.0;
        outColor = texture(s_texture, vec2(x, y));
    }
}

实现效果:

四.九宫格滤镜

如果你跟着博文一直学习到这里,并且自己动手实现了四宫格滤镜,那么九宫格滤镜也只是顺理成章的事了。

九宫格示例代码中,我没有逐个宫格计算实现,而是通过x,y的等分范围来实现

所以也没有逐个添加滤镜效果,

重点在于

九宫格的实现

前文中也提到过,只要找到了

小宫格



大宫格

的对应关系,也完全可以根据

“几宫格”



“几”

,将着色器代码进一步精简,用循环语句来划分宫格。

理解透了原理就万变不离其宗了,代码实现只是形式

如下是九宫格着色器代码:

#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision mediump float;

in vec2 texCoord;//纹理坐标,图片当中的坐标点
out vec4 outColor;

uniform samplerExternalOES s_texture;//图片,采样器

void main(){
    float x = texCoord.x;
    float y = texCoord.y;

    //九宫格滤镜
    float x = texCoord.x;
    float y = texCoord.y;

    if (x < 1.0 / 3.0) {
        x = x * 3.0;
    } else if (x < 2.0 / 3.0) {
        x = (x - 1.0 / 3.0) * 3.0;
    } else {
        x = (x - 2.0 / 3.0) * 3.0;
    }
    if (y <= 1.0 / 3.0) {
        y = y * 3.0;
    } else if (y < 2.0 / 3.0) {
        y = (y - 1.0 / 3.0) * 3.0;
    } else {
        y = (y - 2.0 / 3.0) * 3.0;
    }

    outColor = texture(s_texture, vec2(x, y));
}

实现效果:

五.结束



版权声明:本文为geyichongchujianghu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。