一些简单滤镜效果

466

前言

通过修改Swift+OpenGLES 展示图片中的片元着色器代码,实现对图片的修改完成一些简单滤镜效果。

灰度滤镜

方法

通过对色值修改,然后使图片呈现灰度,对色值修改方案基本如下:

  • 浮点算法:Gray=R0.3+G0.59+B*0.11
  • 整数⽅方法:Gray=(R30+G59+B*11)/100
  • 移位⽅方法:Gray =(R76+G151+B*28)>>8
  • 平均值法:Gray=(R+G+B)/3
  • 仅取绿⾊色:Gray=G

片元着色器修改

对片元着色器修改代码如下:

precision highp float;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
vec3 W = vec3(0.2125,0.7154,0.0721);

void main() {
    vec4 color = texture2D(colorMap, varyTextCoord);
    float gray = dot(color.rgb,W);
    gl_FragColor = vec4(vec3(gray),color.a);
}

效果

颠倒图片

片元着色器

片元着色器修改代码如下:

precision highp float;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;

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

效果

漩涡滤镜

片元着色器

片元着色器修改代码如下,每行都做了详细注释:

precision highp float;

//旋转角度
const float uD = 60.0;
//旋转半径比例
const float uR = 0.6;

varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;

void main() {
    //纹理图片相对大小
    ivec2 ires = ivec2(1,1);
    //相对直径
    float Res = float(ires.y);
    
    vec2 st = varyTextCoord;
    //旋转半径
    float Radius = Res * uR;
    
    //纹理相对坐标
    vec2 xy = Res * st;
    
    //以图片中心点为旋转中心,求与半径向量差目的是为了得到:1.长度是否在旋转范围内,2.角度加上旋转角度
    vec2 dxy = xy - Res/2.0;
    //长度
    float r = length(dxy);
    
    //抛物线递减因子
    float attenValue = (1.0 - (r/Radius) * (r/Radius));
    //旋转角度
    float beta = atan(dxy.y,dxy.x) + radians(uD) * 2.0 *attenValue;
    
    //在旋转范围内进行旋转、然后加上半径向量恢复到纹理相对坐标
    if(r <= Radius) {
        xy = Res/2.0 + r*vec2(cos(beta),sin(beta));
    }
    //重新拿到纹理坐标
    st = xy/Res;
    gl_FragColor = texture2D(colorMap,st);
}

其中vec2 dxy = xy - Res/2.0;的目的已做注释,为更清晰理解见下图:

效果

正方形马赛克滤镜

片元着色器

片元着色器修改代码如下:

precision mediump float;

varying vec2 varyTextCoord;
uniform sampler2D colorMap;

//自定义图片大小,用于分割
const vec2 TexSize = vec2(500,500);
//分割大小即马赛克大小
const vec2 mosaicSize = vec2(20.0,20.0);

void main() {
    vec2 textCoSize = vec2(varyTextCoord.x * TexSize.x, varyTextCoord.y * TexSize.y);
    vec2 mosaicTex = vec2(floor(textCoSize.x/mosaicSize.x) *mosaicSize.x , floor(textCoSize.y/mosaicSize.y) * mosaicSize.y);
    vec2 textC = vec2(mosaicTex.x / TexSize.x, mosaicTex.y / TexSize.y);
    gl_FragColor = texture2D(colorMap,textC);
    
}

效果