上文 OpenGL ES之滤镜处理(1)_分屏滤镜 - 简书讲述了分屏滤镜的处理,本文介绍灰度滤镜与马赛克滤镜的处理。
灰度滤镜
原理
- 浮点算法:
- 整数⽅法:
- 移位⽅法:
- 平均值法:
- 仅取绿⾊:
片元着色器
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
const highp vec3 W = vec3(0.2125,0.7154,0.0721);
void main (void) {
vec4 mask = texture2D(Texture, TextureCoordsVarying);
//将颜⾊mask 与 变换因⼦相乘得到灰度值
float luminance = dot(mask.rgb,W);
gl_FragColor = vec4(vec3(luminance),1.0);
}
马赛克滤镜
⻢赛克效果就是把图⽚的⼀个相当⼤⼩的区域⽤同⼀个点的颜⾊来表示.可以认为是⼤规模的降低图像的分辨率,⽽让图像的⼀些细节隐藏起来。
马赛克滤镜-正方形
原理
- 根据当前纹素坐标 乘以纹理的Size,计算出实际上纹素点的位置;
- 获取周边马赛克的大小;
- 在将其换算回纹理坐标;
- 根据获取到马赛克后的纹理坐标的颜色值;
- 将马赛克颜色值赋值
片元着色器
precision highp float;
uniform sampler2D Texture;
const vec2 TexSize = vec2(400.0,400.0);
const vec2 MosaicSize = vec2(16.0,16.0);
varying vec2 TextureCoordsVarying;
void main (void) {
vec2 intXY = vec2(TextureCoordsVarying.x * TexSize.x, TextureCoordsVarying.y * TexSize.y);
vec2 XYMosaic = vec2(floor(intXY.x / MosaicSize.x) * MosaicSize.x,floor(intXY.y / MosaicSize.y) * MosaicSize.y);
vec2 UVMosaic = vec2(XYMosaic.x / TexSize.x, XYMosaic.y / TexSize.y);
vec4 mask = texture2D(Texture,UVMosaic);
gl_FragColor = vec4(mask.rgb,1.0);
}
马赛克滤镜-六边形
让一张图片分割成由六边形组成,让每个六边形中的颜色相同(直接取六边形中心点的颜色)。
原理
将图片进行分割,取每个六边形的中心点画出一个矩阵。假定矩阵⽐例为$$ 3LEN : \sqrt[]{3}LEN$ ,那么屏幕上的任意点(x, y)所对应的矩阵坐标为
矩形的宽为: ,矩形的⻓为:
。
所以
wx,wy -> 表⽰纹理坐标在所对应的矩阵坐标为
int wx = int(x /(TB * length));
int wy = int(y /(TR * length));
根据矩阵坐标求得对应六边形中心点的坐标。若表示当点在偶数⾏偶数列,或者奇数⾏奇数列的情形,像下方左图这种情况下,只有左上右下有个点是六边形中⼼点。否则为下方有图,右上左下为六边形中心点。
-
点A
vec2(length * 1.5 * float(wx), length * TR * float(wy));
-
点B
vec2(length * 1.5 * float(wx + 1), length * TR * float(wy + 1));
-
点C
vec2(length * 1.5 * float(wx + 1), length * TR * float(wy));
-
点D
vec2(length * 1.5 * float(wx), length * TR * float(wy + 1));
求得中心点坐标后,计算当前纹素坐标距离两个中心点的位置远近判断在哪一个一个六边形当中,最后赋值给该坐标位置中心点的颜色。
片元着色器
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) {
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{
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) {
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{
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 mask = texture2D(Texture,vn);
gl_FragColor = vec4(mask.rgb,1.0);
}
马赛克滤镜-三角形
三角形马赛克滤镜是基于六边形的基础上,将六边形平分为6个三角形。使得每一个三角形中的颜色相同(三角形中心点颜色值)
原理
基于六边形的基础上,计算出点与六边形中心点的夹角,判断点在哪一个三角形当中,获取其三角形中心点的颜色值。
片元着色器代码
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
float mosaicSize = 0.03;
void main (void){
const float TR = 0.866025;
const float PI6 = 0.523599;
float x = TextureCoordsVarying.x;
float y = TextureCoordsVarying.y;
int wx = int(x/(1.5 * mosaicSize));
int wy = int(y/(TR * mosaicSize));
vec2 v1, 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));
}
}
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;
}
网友评论