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,操作更方便哦

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342