OpenGL ES: 濾鏡篇1 -GLSL 灰度,顛倒,旋渦,馬賽克

前提: 使用GLSL實現濾鏡的前提條件是可以用GLSL顯示普通圖片算法

灰度濾鏡bash

原理: 圖片的顯示由三個顏色通道(rgb)決定,而灰度濾鏡全部通道的值相同,也就是說只要獲得亮度即可。下面提供5種方式實現灰度濾鏡(前三種是利用權重來實現)

算法ui

  • 浮點算法: Gray = R * 0.3 + G * 0.59 + B * 0.11
  • 整數算法: Gray = (R * 30 + G * 59 + B * 11) / 100
  • 移位算法: Gray = (R * 76 + G * 151 + B * 28) >> 8
  • 平均值法: Gray = (R + G + B) / 3;
  • 僅取綠色: Gray = G

片元着色器代碼實現:spa

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
//灰度計算比率 (借用GPUImage的值)
const highp vec3 ratio = vec3(0.2125, 0.7154, 0.0721);
void main (void) {
    vec4 mask = texture2D(Texture, TextureCoordsVarying);
    // Gray值
    float luminance = dot(mask.rgb, ratio);
    gl_FragColor = vec4(vec3(luminance), 1.0);
}
複製代碼

顛倒濾鏡3d

原理: 在Y軸上反轉紋理座標.

片元着色器代碼實現:code

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

void main (void) {
//y軸座標反轉
    vec4 color = texture2D(Texture, vec2(TextureCoordsVarying.x, 1.0 - TextureCoordsVarying.y));
    gl_FragColor = color;
}
複製代碼

旋渦濾鏡orm

原理: 圖形漩渦主要是在某個半徑範圍內,把當前採樣點旋轉必定角度,旋轉之後當前點的顏色就被旋轉後的點的顏色代替,所以整個半徑範圍裏會有旋轉的效果。 若是旋轉的時候旋轉角度隨着當前點距離半徑的距離遞減,整個圖像就會出現漩渦效果,如上圖同樣。 這裏會使用拋物線遞減因子: (1.0 - (r / Radius) * (r / Radius))

片元着色器代碼實現:cdn

precision mediump float;
uniform sampler2D Texture;
//旋渦旋轉角度
const float uD = 80.0;
//旋渦半徑,範圍(0 ~ 0.5)
const float uR = 0.5;
//紋理座標
varying vec2 TextureCoordsVarying;

void main()
{
    //旋渦半徑
    float Radius = uR;
    //當前紋理座標
    vec2 xy = TextureCoordsVarying;
    //當前紋理到中心點的向量
    vec2 dxy = xy - vec2(0.5, 0.5);
    //當前紋理到中心點距離
    float r = length(dxy);
    //旋轉角度變化
    float beta = atan(dxy.y, dxy.x) + radians(uD) * 2.0 * ( 1.0 -(r/Radius)*(r/Radius));
    //旋渦範圍內的座標變化
    if(r<=Radius)
    {
        xy = 0.5 + r * vec2(cos(beta), sin(beta));
    }
    //將旋轉的紋理座標替換原始紋理座標TextureCoordsVarying 獲取對應像素點的顏⾊. 
    vec3 irgb = texture2D(Texture, xy).rgb;
    //將計算後的顏⾊填充到像素點中 gl_FragColor
    gl_FragColor = vec4( irgb, 1.0 );
}

複製代碼

馬賽克濾鏡blog

原理: 馬賽克效果就是把圖片的一個至關大小的區域用同一個點的顏色來表示,能夠認爲是大規模的下降圖像的分辨率,而讓圖片的一些細節隱藏起來。

1.矩形馬賽克 片元着色器代碼實現:圖片

precision mediump float;
varying vec2 TextureCoordsVarying;
uniform sampler2D Texture;
//馬賽克矩形所佔紋理範圍比例
const vec2 mosaicSizeRatio = vec2(0.05, 0.05);

void main()
{
    //紋理範圍能夠切割多少個矩形馬賽克
    vec2 totalXY = vec2(floor(1.0 / mosaicSizeRatio.x), floor(1.0 / mosaicSizeRatio.y));
    //當前紋理在哪一個矩形馬賽克範圍
    vec2 eachXY = vec2(floor(TextureCoordsVarying.x / mosaicSizeRatio.x), floor(TextureCoordsVarying.y / mosaicSizeRatio.y));
   //當前紋理塊對應的紋理座標
    vec2 UVMosaic = vec2(eachXY.x / totalXY.x, eachXY.y / totalXY.y);
    vec4 color = texture2D(Texture, UVMosaic);
    gl_FragColor = color;
}
複製代碼

2.六邊形馬賽克

思路: 咱們須要作的效果就是讓一張圖片,分割成由六邊形組成,讓每一個六邊形中的顏色相同,下面採用直接取六邊形中心點像素來實現. 再次分割,取每一個六邊形的中心點畫出矩形陣,以下:

假定咱們設定的矩陣比例爲 a LEN : bLEN ,那麼屏幕上的任意 點(x, y)所對應的矩陣座標爲(int(x/(a LEN)), int(y/ (bLEN)))。

(wx, wy) 表示紋理座標在所對應的矩陣座標爲:

wx = int(x/(a * length))

wy = int(y/(b * length))

根據行和列的奇偶數排列規則,計算一個矩形塊內的任意點距離哪一個六邊形的距離短,就屬於哪一個六邊形.

片元着色器代碼實現:

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
/// 馬賽克大小比率
const float mosaicSize = 0.05;

void main (void)
{
    //馬賽克大小比率
    float length = mosaicSize;
    // 矩形b
    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);
    //v1, v2爲矩形頂點(六邊形的中心點)的紋理座標
    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;
    
}
複製代碼
相關文章
相關標籤/搜索