OpenGLES滤镜(二)---万恶的马赛克+灰度

一.先看看整体效果


整体效果

二.灰度滤镜     

         灰度滤镜实现原理是获取像素点的颜色值,通过改变该像素点的颜色值实现灰度滤镜,究其根本是通过RGB保持平衡填充,或者保留一个亮度值(即绿色,在人眼中,绿色的亮度是最显眼的,绿色值越深,在肉眼观察中图片越暗淡,这是眼睛的一种生理现象)

        灰度滤镜算法:

                              1)浮点算法:Gray=R*0.3+G*0.59+B*0.11

                                2)整数⽅法:Gray=(R*30+G*59+B*11)/100

                                3)移位⽅法:Gray =(R*76+G*151+B*28)>>8

                                4)平均值法:Gray=(R+G+B)/3    

                                5)仅取绿⾊:Gray=G

        在自定义片元着色器中浮点算法:

                            precision highp float;

                            uniform sampler2D Texture;

                            varyingvec2TextureCoordsVarying;

                            const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);----->权重,该参数取值样本来自于GPUimage灰度滤镜参数

                        voidmain (void) {

                                vec4mask =texture2D(Texture, TextureCoordsVarying);

                                floatluminance =dot(mask.rgb, W);

                                gl_FragColor=vec4(vec3(luminance),1.0);

                                }

        dot(mask.rgb, W)点乘,让原像素点的颜色值乘以权重,得到一个新的RGB颜色值,并填充。

        仅取绿色:

                            precision highpfloat;

                            uniform sampler2D Texture;

                            varying vec2 TextureCoordsVarying;

                            voidmain()

                                    {                      

                                      //获取对应纹理坐标系下色颜色值

                                        vec4 mask=texture2D(Texture,TextureCoordsVarying);

                                        //将RGB全部设置为G,即GRB全部取绿色值

                                        gl_FragColor=vec4(mask.g,mask.g,mask.g,1.0);

                                    }

        其他算法,请参照服点算法,这里不一一举例了

    

灰度滤镜效果图

三.万恶的马赛克

            马赛克原理:把图片的一个相当大小的区域用同一个颜色值来表示,可以认为是大规模的降低图像的分辨率,从而让图像的一些细节隐藏起来

        3.1正方形马赛克原理图:

正方形马赛克

        当拿到蓝色块的纹理坐标,对应的在(16,16)范围内只显示该像素点的颜色值

        片元着色器代码:

                precision mediump float;

                varyingvec2TextureCoordsVarying;

                uniform sampler2D Texture;

                constvec2TexSize =vec2(400.0,400.0);----->(该参数最少>=图片的宽高)

                constvec2mosaicSize =vec2(16.0,16.0);---->(根据实际的情况,该参数尽量合适)

                voidmain()

                {

                        vec2intXY =vec2(TextureCoordsVarying.x*TexSize.x, TextureCoordsVarying.y*TexSize.y);

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

                        //换算回纹理坐标

                        vec2UVMosaic =vec2(XYMosaic.x/TexSize.x, XYMosaic.y/TexSize.y);

                        vec4color =texture2D(Texture, UVMosaic);

                        gl_FragColor= color;

                }


正方形马赛克效果图

3.2六边形马赛克

        思路: 我们要做的效果就是让⼀张图⽚,分割成由六边形组成,让每个六边形中的颜⾊相同(直接取六边形中⼼点像素RGB较⽅便,我们这⾥采⽤的就是这种⽅法)将它进⾏分割,取每个六边形的中⼼点画出⼀个矩阵。


图片分割成六边形

        首先我们设置举行的长宽:画出很多⻓和宽⽐例为 3:√3 的的矩形阵。然后我们可以对每个点进⾏编号,假如我们的屏幕的左上点为上图的(0,0)点,则屏幕上的任⼀点我们找到它所对应的那个矩形了,假定我们设定的矩阵⽐例为 3*LEN : √3*LEN ,那么屏幕上的任意点(x, y)所对应的矩阵坐标为(int(x/(3*LEN)), int(y/(√3*LEN)))。wx,wy -> 表⽰纹理坐标在所对应的矩阵坐标为 int wx = int(x /( 1.5 * length)); int wy = int(y /(TR * length))。

        3:√3的来源:设置矩形的长宽比例值TR、TB(TB:TR 符合比例 3:√3)计算过程如下:

图片来自于:https://www.jianshu.com/p/dcfb5515dbab

        获取纹理坐标的x,y,根据纹理坐标计算对应的矩形坐标wx、wy,假设矩阵的比例为3*len:√3*len,那么纹理坐标(x,y)对应的矩阵坐标为:

图片来自于:https://www.jianshu.com/p/dcfb5515dbab

        根据行列的奇偶情况,求对应的中心点纹理坐标v1、v2

        偶行偶列:(0,0)(1,1)/,即左上、右下

        偶行奇列:(0,1)(1,0)\,即左下、右上

        奇行偶列:(0,1)(1,0)\,即左下、右上

        奇行奇列:(0,0)(1,1)/,即左上、右下

        最终就两种情况:


        最终汇总起来也只有2种情况,(0,0)(1,1) 和 (0,1)(1,0),如下图所示


图片来自于:https://www.jianshu.com/p/dcfb5515dbab

其中单个矩阵中,4个点的坐标计算公式如下:

- 对于计算中的wx+1,拿(1,0)点来说,wx+1等同于(1,0)与(0,0)之间相差一个矩形的长,这个长度为1,为了得到(1,0)点的坐标,要在(0,0)点坐标的基础上,将wx增加一个长

- 对于计算中的wy+1,拿(0,1)点来说,wy+1等同于(0,0)与(0,1)之间相差一个矩形的高,这个长度为1,为了得到(0,1)点的坐标,要在(0,0)点坐标的基础上,将wy增加一个高


坐标计算方式

最后根据勾股定理,计像素点距离两个中心点的距离s1、s2根据距离公式求像素点距离两个中心点的距离s1、s2


图片来自于:https://www.jianshu.com/p/dcfb5515dbab

片元着色器代码:

            precision highp float;

            uniform sampler2D Texture;

            varyingvec2TextureCoordsVarying;

            constfloatmosaicSize =0.03;

            voidmain (void)

            {

                floatlength= mosaicSize;

                floatTR =0.866025;//矩形的高的比例为√3,取值 √3/2 ,也可以直接取√3

                floatTB =1.5;//矩形的长的比例为3,取值 3/2 = 1.5,也可以直接取3

                floatx = TextureCoordsVarying.x;//取出纹理坐标

                floaty = TextureCoordsVarying.y;//取出纹理坐标

                intwx =int(x / TB /length);//根据纹理坐标计算出对应的矩阵坐标 //即 矩阵坐标wx = int(纹理坐标x/ 矩阵长),矩阵长 = TB*len//即 矩阵坐标wy = int(纹理坐标y/ 矩阵宽),矩阵宽 = TR*len

                intwy =int(y / TR /length);

                vec2v1, v2, vn;

                if(wx/2*2== wx) {//判断wx是否为偶数,等价于 wx % 2 == 0

                        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));

        }

    }

            floats1 =sqrt(pow(v1.x - x,2.0) +pow(v1.y - y,2.0));

            floats2 =sqrt(pow(v2.x - x,2.0) +pow(v2.y - y,2.0));

            if(s1 < s2) {

                vn = v1;

            }else{

                vn = v2;

            }

            vec4color =texture2D(Texture, vn);

            gl_FragColor= color;

}


六边形马赛克

3.3三角形马赛克

        三角形马赛克是由六边形马赛克演变而来,得到三角形的前提,就是的先有六边形,然后将正六边形6等分,每个三角形都是正三角形,然后求出纹理坐标与中心点的夹角,同时求出三角形的中心点,根据夹角判断,夹角属于哪个三角形,就将该三角形的中心点颜色作为整个三角形的纹素

precision highp float;

uniform sampler2D Texture;

varyingvec2TextureCoordsVarying;

floatmosaicSize =0.03;

voidmain (void){


    constfloatTR =0.866025;

    constfloatPI6 =0.523599;


    floatx = TextureCoordsVarying.x;

    floaty = TextureCoordsVarying.y;

    intwx =int(x/(1.5* mosaicSize));

    intwy =int(y/(TR * mosaicSize));

    vec2v1, v2, vn;

    if(wx /2*2== wx) {

        if(wy/2*2== wy) {

            v1 =vec2(mosaicSize *1.5*float(wx), mosaicSize * TR *float(wy));

            v2 =vec2(mosaicSize *1.5*float(wx +1), mosaicSize * TR *float(wy +1));

        }else{

            v1 =vec2(mosaicSize *1.5*float(wx), mosaicSize * TR *float(wy +1));

            v2 =vec2(mosaicSize *1.5*float(wx +1), mosaicSize * TR *float(wy));

        }

    }else{

        if(wy/2*2== wy) {

            v1 =vec2(mosaicSize *1.5*float(wx), mosaicSize * TR *float(wy +1));

            v2 =vec2(mosaicSize *1.5*float(wx+1), mosaicSize * TR *float(wy));

        }else{

            v1 =vec2(mosaicSize *1.5*float(wx), mosaicSize * TR *float(wy));

            v2 =vec2(mosaicSize *1.5*float(wx +1), mosaicSize * TR *float(wy+1));

        }

    }

    floats1 =sqrt(pow(v1.x - x,2.0) +pow(v1.y - y,2.0));

    floats2 =sqrt(pow(v2.x - x,2.0) +pow(v2.y - y,2.0));

    if(s1 < s2) {

        vn = v1;

    }else{

        vn = v2;

    }


    vec4mid =texture2D(Texture, vn);

    floata =atan((x - vn.x)/(y - vn.y));

    vec2area1 =vec2(vn.x, vn.y - mosaicSize * TR /2.0);

    vec2area2 =vec2(vn.x + mosaicSize /2.0, vn.y - mosaicSize * TR /2.0);

    vec2area3 =vec2(vn.x + mosaicSize /2.0, vn.y + mosaicSize * TR /2.0);

    vec2area4 =vec2(vn.x, vn.y + mosaicSize * TR /2.0);

    vec2area5 =vec2(vn.x - mosaicSize /2.0, vn.y + mosaicSize * TR /2.0);

    vec2area6 =vec2(vn.x - mosaicSize /2.0, vn.y - mosaicSize * TR /2.0);

    if(a >= PI6 && a < PI6 *3.0) {

        vn = area1;

    }elseif(a >= PI6 *3.0&& a < PI6 *5.0) {

        vn = area2;

    }elseif((a >= PI6 *5.0&& a <= PI6 *6.0)|| (a<-PI6 *5.0&& a>-PI6*6.0)) {

        vn = area3;

    }elseif(a < -PI6 *3.0&& a >= -PI6 *5.0) {

        vn = area4;

    }elseif(a <= -PI6 && a> -PI6 *3.0) {

        vn = area5;

    }elseif(a > -PI6 && a < PI6)

    {

        vn = area6;

    }

    vec4color =texture2D(Texture, vn);

    gl_FragColor= color;

}

最后附上Demo:链接: https://pan.baidu.com/s/1S7m5OKJFi77FcqDVaAZ0DQ 提取码: isns 复制这段内容后打开百度网盘手机App,操作更方便哦

你可能感兴趣的:(OpenGLES滤镜(二)---万恶的马赛克+灰度)