灰度濾鏡效果就是讓一張彩色的圖片變成灰白的。
灰度濾鏡公式
- 浮點(diǎn)算法:
Gray=R*0.3+G*0.59+B*0.11
- 整數(shù)?法:
Gray=(R*30+G*59+B*11)/100
- 移位?法:
Gray =(R*76+G*151+B*28)>>8;
- 平均值法:
Gray=(R+G+B)/3;
- 僅取綠?:
Gray=G凄硼;
代碼實(shí)現(xiàn)
- 我們首先設(shè)定一個(gè)權(quán)重懦傍,借鑒了
GPUImage
浪感,綠色值最高是因?yàn)槿藗儗G色敏感度最高
const highp vec3 W = vec3(0.2125,0.7154,0.0721);
- 然后計(jì)算出紋素中的灰度值,
dot
指的是點(diǎn)乘
//計(jì)算灰度值
float luminance = dot(mask.rgb,W);
- 最后將灰度值轉(zhuǎn)化為紋素返回給
gl_FragColor
gl_FragColor = vec4(vec3(luminance),0.1);
- 整體片元著色器代碼如下:
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
const highp vec3 W = vec3(0.2125,0.7154,0.0721);
void main (void) {
//獲取對應(yīng)紋理坐標(biāo)系下色顏色值
vec4 mask = texture2D(Texture, TextureCoordsVarying);
//獲取灰度值
float luminance = dot(mask.rgb,W);
//將灰度值轉(zhuǎn)化成顏色值
gl_FragColor = vec4(vec3(luminance),0.1);
}
正方形馬賽克
原理
馬賽克效果就是把圖?的?個(gè)相當(dāng)??的區(qū)域?同?個(gè)點(diǎn)的顏?來表示
,從而隱藏關(guān)鍵信息。
我們可以把圖片切割成無數(shù)的小的框框,然后再取小框框中某個(gè)點(diǎn)的顏色然后再把取出去的顏色整體覆蓋到框框中麻顶,就會出現(xiàn)一個(gè)色塊一個(gè)色塊的效果赦抖,就呈現(xiàn)出了馬賽克的效果
代碼實(shí)現(xiàn)
- 首先,假定紋理的大小和馬賽克的大小
馬賽克設(shè)置的越小辅肾,馬賽克越密集
//假設(shè)紋理大小為400.0 * 400.0
const vec2 TextSize = vec2(400.0,400.0);
//設(shè)置馬賽克大小為10.0 * 10.0
const vec2 MosaicSize = vec2(10.0,10.0);
- 獲取馬賽克在假設(shè)紋理中的實(shí)際坐標(biāo)
//獲取紋理中的實(shí)際坐標(biāo)
vec2 intXY = vec2(TextureCoordsVarying.x * TextSize.x , TextureCoordsVarying.y * TextSize.y);
- 計(jì)算一個(gè)小馬賽克的坐標(biāo)
//計(jì)算小馬賽克的坐標(biāo)
vec2 XYMosaic = vec2(floor(intXY.x/MosaicSize.x) * MosaicSize.x , floor(intXY.y/MosaicSize.y) * MosaicSize.y);
floor()
是glsl的一個(gè)內(nèi)建函數(shù),返回?于/等于X的最?整數(shù)值
队萤,即向下取整。
- 最后換算出在紋理坐標(biāo)中的位置
//獲取紋理坐標(biāo)中的位置
vec2 UVMosaic = vec2(XYMosaic.x / TextSize.x , XYMosaic.y / TextSize.y);
- 賦值給
gl_FragColor
vec4 mask = texture2D(Texture, UVMosaic);
gl_FragColor = mask;
- 整體代碼如下:
precision highp float;
uniform sampler2D Texture;
const vec2 TextSize = vec2(400.0,400.0);
const vec2 MosaicSize = vec2(10.0,10.0);
varying vec2 TextureCoordsVarying;
void main (void) {
vec2 intXY = vec2(TextureCoordsVarying.x * TextSize.x , TextureCoordsVarying.y * TextSize.y);
vec2 XYMosaic = vec2(floor(intXY.x/MosaicSize.x) * MosaicSize.x , floor(intXY.y/MosaicSize.y) * MosaicSize.y);
vec2 UVMosaic = vec2(XYMosaic.x / TextSize.x , XYMosaic.y / TextSize.y);
vec4 mask = texture2D(Texture, UVMosaic);
gl_FragColor = mask;
}
正六邊形馬賽克
原理
int wx = int(x /( 1.5 * length)); int wy = int(y /(TR * length))赵辕。
3:√3的來源:設(shè)置矩形的長寬比例值TR、TB(TB:TR 符合比例 3:√3)計(jì)算過程如下:
獲取紋理坐標(biāo)的x杯活,y匆帚,根據(jù)紋理坐標(biāo)計(jì)算對應(yīng)的矩形坐標(biāo)wx、wy旁钧,假設(shè)矩陣的比例為3len:√3len,那么紋理坐標(biāo)(x互拾,y)對應(yīng)的矩陣坐標(biāo)為:
根據(jù)行列的奇偶情況歪今,求對應(yīng)的中心點(diǎn)紋理坐標(biāo)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),如下圖所示
其中單個(gè)矩陣中巡语,4個(gè)點(diǎn)的坐標(biāo)計(jì)算公式如下:
對于計(jì)算中的wx+1翎蹈,拿(1,0)點(diǎn)來說男公,wx+1等同于(1荤堪,0)與(0,0)之間相差一個(gè)矩形的長枢赔,這個(gè)長度為1澄阳,為了得到(1,0)點(diǎn)的坐標(biāo)踏拜,要在(0碎赢,0)點(diǎn)坐標(biāo)的基礎(chǔ)上,將wx增加一個(gè)長
對于計(jì)算中的wy+1速梗,拿(0肮塞,1)點(diǎn)來說,wy+1等同于(0姻锁,0)與(0枕赵,1)之間相差一個(gè)矩形的高,這個(gè)長度為1位隶,為了得到(0拷窜,1)點(diǎn)的坐標(biāo),要在(0涧黄,0)點(diǎn)坐標(biāo)的基礎(chǔ)上篮昧,將wy增加一個(gè)高
最后根據(jù)勾股定理,計(jì)像素點(diǎn)距離兩個(gè)中心點(diǎn)的距離s1笋妥、s2根據(jù)距離公式求像素點(diǎn)距離兩個(gè)中心點(diǎn)的距離s1懊昨、s2
作者:楓紫_6174
鏈接:http://www.reibang.com/p/e390baf1089b
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)挽鞠,非商業(yè)轉(zhuǎn)載請注明出處疚颊。
//TR = √3/2
int wx = int(x /( 1.5 * length));
int wy = int(y /(TR * length));
所以換算出坐標(biāo)
- 左上角,
vec2(length * 1.5 * float(wx), length * TR * float(wy))
- 左下角信认,
vec2(length * 1.5 * float(wx), length * TR * float(wy + 1))
- 右上角材义,
vec2(length * 1.5 * float(wx + 1), length * TR * float(wy))
- 右下角,
vec2(length * 1.5 * float(wx + 1), length * TR * float(wy + 1))
所以我們只需要判斷紋理對應(yīng)的點(diǎn)離哪個(gè)中心點(diǎn)近即可
判斷C離A點(diǎn)近還是B點(diǎn)近嫁赏,我們只需要求出C到A和C到B的距離即可其掂,
//pow是(v1.x - x)的平方
//sqrt是開根號
float s = sqrt(pow(v1.x - x, 2.0) + pow(v1.y - y, 2.0));
現(xiàn)在我們要判斷4種情況,如圖
分別為:
- 偶行偶列潦蝇,A
//中心點(diǎn)的坐標(biāo)分別為
v1 = vec2(length * 1.5 * float(wx), length * TR * float(wy));
v2 = vec2(length * 1.5 * float(wx + 1), length * TR * float(wy + 1));
- 偶行奇列款熬,B
//中心點(diǎn)的坐標(biāo)分別為
v1 = vec2(length * 1.5 * float(wx), length * TR * float(wy + 1));
v2 = vec2(length * 1.5 * float(wx + 1), length * TR * float(wy));
- 奇行偶列深寥,C
//中心點(diǎn)的坐標(biāo)分別為
v1 = vec2(length * 1.5 * float(wx), length * TR * float(wy + 1));
v2 = vec2(length * 1.5 * float(wx + 1), length * TR * float(wy));
- 奇行奇列,D
//中心點(diǎn)的坐標(biāo)分別為
v1 = vec2(length * 1.5 * float(wx), length * TR * float(wy));
v2 = vec2(length * 1.5 * float(wx + 1), length * TR * float(wy + 1));
最后進(jìn)行比較贤牛,將小的點(diǎn)的坐標(biāo)當(dāng)成改區(qū)域坐標(biāo)即可
完整代碼如下:
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 TB = 1.5;
float x = TextureCoordsVarying.x;
float y = TextureCoordsVarying.y;
int wx = int(x / TB / 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;
}
三角形馬賽克
之前我們已經(jīng)計(jì)算出了正六邊形馬賽克惋鹅,根據(jù)我們紋理的坐標(biāo)可以知道究竟在哪個(gè)六邊形里面,那么三角形就是在六邊形的基礎(chǔ)上進(jìn)行細(xì)分殉簸,將正六邊形切割成六塊闰集,判斷點(diǎn)究竟在哪個(gè)三角形里面
,如圖
- 首先求出紋理坐標(biāo)點(diǎn)和中心點(diǎn)之間的夾角
float a = atan((x - vn.x)/(y - vn.y));
- 分別求出六個(gè)區(qū)域中心點(diǎn)的坐標(biāo)
vec2 area1 = vec2(vn.x, vn.y - mosaicSize * TR / 2.0);
vec2 area2 = vec2(vn.x + mosaicSize / 2.0, vn.y - mosaicSize * TR / 2.0);
vec2 area3 = vec2(vn.x + mosaicSize / 2.0, vn.y + mosaicSize * TR / 2.0);
vec2 area4 = vec2(vn.x, vn.y + mosaicSize * TR / 2.0);
vec2 area5 = vec2(vn.x - mosaicSize / 2.0, vn.y + mosaicSize * TR / 2.0);
vec2 area6 = vec2(vn.x - mosaicSize / 2.0, vn.y - mosaicSize * TR / 2.0);
- 判斷紋理坐標(biāo)在哪個(gè)區(qū)域
const float PI6 = 0.523599;
if (a >= PI6 && a < PI6 * 3.0) {
vn = area1;
} else if (a >= PI6 * 3.0 && a < PI6 * 5.0) {
vn = area2;
} else if ((a >= PI6 * 5.0 && a <= PI6 * 6.0)|| (a<-PI6 * 5.0 && a>-PI6*6.0)) {
vn = area3;
} else if (a < -PI6 * 3.0 && a >= -PI6 * 5.0) {
vn = area4;
} else if(a <= -PI6 && a> -PI6 * 3.0) {
vn = area5;
} else if (a > -PI6 && a < PI6)
{
vn = area6;
}
- 完整代碼如下
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
const float mosaicSize = 0.03;
void main (void) {
float length = mosaicSize;
const float PI6 = 0.523599;
float TR = 0.866025;
float TB = 1.5;
float x = TextureCoordsVarying.x;
float y = TextureCoordsVarying.y;
int wx = int(x / TB / 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 mid = texture2D(Texture, vn);
float a = atan((x - vn.x)/(y - vn.y));
vec2 area1 = vec2(vn.x, vn.y - mosaicSize * TR / 2.0);
vec2 area2 = vec2(vn.x + mosaicSize / 2.0, vn.y - mosaicSize * TR / 2.0);
vec2 area3 = vec2(vn.x + mosaicSize / 2.0, vn.y + mosaicSize * TR / 2.0);
vec2 area4 = vec2(vn.x, vn.y + mosaicSize * TR / 2.0);
vec2 area5 = vec2(vn.x - mosaicSize / 2.0, vn.y + mosaicSize * TR / 2.0);
vec2 area6 = vec2(vn.x - mosaicSize / 2.0, vn.y - mosaicSize * TR / 2.0);
if (a >= PI6 && a < PI6 * 3.0) {
vn = area1;
} else if (a >= PI6 * 3.0 && a < PI6 * 5.0) {
vn = area2;
} else if ((a >= PI6 * 5.0 && a <= PI6 * 6.0)|| (a<-PI6 * 5.0 && a>-PI6*6.0)) {
vn = area3;
} else if (a < -PI6 * 3.0 && a >= -PI6 * 5.0) {
vn = area4;
} else if(a <= -PI6 && a> -PI6 * 3.0) {
vn = area5;
} else if (a > -PI6 && a < PI6)
{
vn = area6;
}
vec4 color = texture2D(Texture, vn);
gl_FragColor = color;
}