音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜

灰度滤镜

灰度滤镜就是获取我们YUV颜色空间里的亮度值Y,我们现在只讲解FragmentShader改动的部分,其他的顶点着色器中的代码是不用改动的。
灰度滤镜用很多中设置方法:

1、仅取绿色值法 - 将三种RGB色值都设置为G分量的值

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);

void main (void) {
    
    vec4 mask = texture2D(Texture, TextureCoordsVarying);
    gl_FragColor = vec4(mask.g,mask.g,mask.g,1.0);
}

其中mask纹理像素值中的RGB全部设置为了mask中的G分量值。
音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜_第1张图片
绿色值法灰度

2、浮点算法(权值法) - 对其中的颜色分量设置权重,我们设置的权重是按照GPUImage中的权重进行设置的(0.2125, 0.7154, 0.0721),看代码

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);

void main (void) {
    
    vec4 mask = texture2D(Texture, TextureCoordsVarying);
    float luminance = dot(mask.rgb, W);
    gl_FragColor = vec4(vec3(luminance), 1.0);
}

按照我们设置的权重值,分别为rgb中的分量设置权重,比较容易理解
音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜_第2张图片
浮点算法

这两个滤镜方法进行比较,其实仔细观察还是能看出下边的浮点算法滤镜的灰度会更纯好一些,上边的图片还是有一些其他颜色

颠倒滤镜

颠倒滤镜其实就是讲图片进行上下/左右的反转,这里我们以上下反转作为实例,直接看片元着色器部分的代码

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;

void main (void) {
    
    vec4 color = texture2D(Texture, vec2(TextureCoordsVarying.x, 1.0 - TextureCoordsVarying.y));
    
    gl_FragColor = color;
}

其实只是将y方向的分量进行了反转,即用1-实际的纹理坐标中的y值,就得到了上下反转的结果,还是比较简单的
音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜_第3张图片
颠倒滤镜

旋涡滤镜

旋涡滤镜其实就是将照片中间部分纹理进行一个一个旋转,并且随着半径增大旋转角度也会增大,直接看片元着色器中的代码部分

precision mediump float;

const float PI = 3.14159265;
uniform sampler2D Texture;

const float uD = 80.0;
const float uR = 0.5;

varying vec2 TextureCoordsVarying;

void main()
{
    ivec2 ires = ivec2(512, 512);
    float Res = float(ires.s);
    
    vec2 st = TextureCoordsVarying;
    float Radius = Res * uR;
    
    vec2 xy = Res * st;
    
    vec2 dxy = xy - vec2(Res/2., Res/2.);
    float r = length(dxy);
    
    //(1.0 - r/Radius);
    float beta = atan(dxy.y, dxy.x) + radians(uD) * 2.0 * (-(r/Radius)*(r/Radius) + 1.0);
    
    vec2 xy1 = xy;
    if(r<=Radius)
    {
        xy1 = Res/2. + r*vec2(cos(beta), sin(beta));
    }
    
    st = xy1/Res;
    
    vec3 irgb = texture2D(Texture, st).rgb;
    
    gl_FragColor = vec4( irgb, 1.0 );
}

PI:我们的计算中的π,取值3.14159265
uR:设置为0.5,其实就是为了取旋涡半径用到的
ivec2:整形的二维向量,这里的ires其实就是一个512宽高的正方形
Res:取出当前正方形的边长
uD:旋转的角度,Radius是我们旋转的半径
xy:通过直径获得纹理坐标对应的物体坐标
dxy:取出纹理坐标减去半径之后的具体物体坐标
r:当前半径

最重要的旋转角度如何设置?

float beta = atan(dxy.y, dxy.x) + radians(uD) * 2.0 * (-(r/Radius)*(r/Radius) + 1.0);

atan(dxy.y, dxy.x):获取的当前的夹角,如果不设置其他的值,那么当前图片没有任何旋转效果。
radians(uD) * 2.0:在原来夹角的基础上加上我们设置的旋转角度802 = 160
(-(r/Radius)
(r/Radius) + 1.0):抛物线衰减因子,通过距离圆心的距离计算我们旋转衰减的增益值

假如我们的向量的模r小于当前的正方形的一半也就是当前圆的半径:
r*vec2(cos(beta), sin(beta)) :旋涡效果
Res/2.:半径
得出旋转后的坐标
st = xy1/Res - 计算旋转后的纹理坐标

最终得到我们的实际显示颜色
音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜_第4张图片
旋涡滤镜

正方形马赛克

正方形马赛克就是马赛克的形状是正方形的
看代码部分

precision mediump float;

varying vec2 TextureCoordsVarying;
uniform sampler2D Texture;
//纹理图像尺寸
const vec2 TexSize = vec2(400.0, 400.0);
//马赛克设置的实际尺寸
const vec2 mosaicSize = vec2(10.0, 10.0);

void main()
{
    //实际图像位置
    vec2 intXY = vec2(TextureCoordsVarying.x*TexSize.x, TextureCoordsVarying.y*TexSize.y);
    //floor返回小于、等于x的最大整数
    //通过出发公式可以获取到某一段以内的数值都设置为同一个值
    vec2 XYMosaic = vec2(floor(intXY.x/mosaicSize.x)*mosaicSize.x, floor(intXY.y/mosaicSize.y)*mosaicSize.y);
    vec2 UVMosaic = vec2(XYMosaic.x/TexSize.x, XYMosaic.y/TexSize.y);
    vec4 color = texture2D(Texture, UVMosaic);
    gl_FragColor = color;
}

其中下边的方法是关键,如果在某一区间内,将这一段区域的像素值都设置为某一个整数位置的像素值,达到正方形马赛克的效果

 vec2 XYMosaic = vec2(floor(intXY.x/mosaicSize.x)*mosaicSize.x, floor(intXY.y/mosaicSize.y)*mosaicSize.y);

六边形马赛克

六边形的马赛克就稍微有点复杂了,我们需要知道六边形的几何知识然后在解释,让自己更加理解.

我们将一张图片分割成六边形,并且让每一个六边形的颜色相同(取六边型的中心点作为我们整个六边形的颜色值),将其分割,分割之后其实有四种不同的矩形将一个六边形分割开来。

音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜_第5张图片
六边形和其像素点的选择

我们对照代码来分析:

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;

//六边型的增量
const float mosaicSize = 0.03;

void main (void)
{
    float length = mosaicSize;
    float TR = 0.866025;
    
    //纹理坐标值
    float x = TextureCoordsVarying.x;
    float y = TextureCoordsVarying.y;
    
    //转化为矩阵中的坐标
    int wx = int(x / 1.5 / length);
    int wy = int(y / TR / length);
    vec2 v1, v2, vn;
    
    //分析矩阵中的坐标是在奇数还是在偶数行,根据奇数偶数值来确定我们的矩阵的角标坐标值
    if (wx/2 * 2 == wx) {
        if (wy/2 * 2 == wy) {
            //(0,0),(1,1)
            v1 = vec2(length * 1.5 * float(wx), length * TR * float(wy));
            v2 = vec2(length * 1.5 * float(wx + 1), length * TR * float(wy + 1));
        } else {
            //(0,1),(1,0)
            v1 = vec2(length * 1.5 * float(wx), length * TR * float(wy + 1));
            v2 = vec2(length * 1.5 * float(wx + 1), length * TR * float(wy));
        }
    }else {
        if (wy/2 * 2 == wy) {
            //(0,1),(1,0)
            v1 = vec2(length * 1.5 * float(wx), length * TR * float(wy + 1));
            v2 = vec2(length * 1.5 * float(wx + 1), length * TR * float(wy));
        } else {
            //(0,0),(1,1)
            v1 = vec2(length * 1.5 * float(wx), length * TR * float(wy));
            v2 = vec2(length * 1.5 * float(wx + 1), length * TR * float(wy + 1));
        }
    }
    
    //获取距离
    float s1 = sqrt(pow(v1.x - x, 2.0) + pow(v1.y - y, 2.0));
    float s2 = sqrt(pow(v2.x - x, 2.0) + pow(v2.y - y, 2.0));
    
    //设置具体的纹理坐标
    if (s1 < s2) {
        vn = v1;
    } else {
        vn = v2;
    }
    vec4 color = texture2D(Texture, vn);
    
    gl_FragColor = color;
    
}

首先我们应该知道一个六边型的宽高比是3:√3,所以我们设置组成六边型的矩形比例也是3:√3,然后乘以一个增量mosaicSize = 0.03,然后我们将原纹理像素坐标转化到我们的矩形中得到矩形的坐标值

 int wx = int(x / 1.5 / length);
 int wy = int(y / TR / length);

然后先看一个纹理元素的坐标
音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜_第6张图片
纹理坐标

纹理坐标对应到我们六边形中组成的矩形时,通过上边矩阵的坐标值反推得到原始纹理坐标值,然后对应纹理坐标系中的变换得到矩阵纹理坐标点
音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜_第7张图片
矩形定点的纹理坐标

接下来,我们分析整个由六边形组成的图中,矩阵的坐标到底应该参考哪一个点
由最上边的图中可以知道,当当前位置在
横轴是偶数,纵轴是奇数的向量位置取左上角右下角
横轴是偶数,纵轴是偶数的向量位置取左下角右上角
横轴是奇数,纵轴是奇数的向量位置取左上角右下角
横轴是奇数,纵轴是偶数的向量位置取左下角右上角

所以才有了上边的判断坐标的代码

最后根据距离这两个角的距离,确定应该采用哪一个纹理坐标获取当前的纹理像素值,看效果如下
音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜_第8张图片
六边形马赛克

你可能感兴趣的:(音视频开发 - 灰度/颠倒/旋涡/正方形马赛克/六边形马赛克滤镜)