前言
这篇文章是为了让大家了解在小视频或美图等软件中,如何利用OpenGL ES实现分屏滤镜,并理解实现的原理。
二分屏滤镜实现
首先看一下下图中的左边原图的纹理坐标。在纹理坐标系中,原点是在左下角。有关纹理坐标系可以参考纹理坐标解析
下图是我们需要实现的效果:
实现思路是这样的: 判断纹理的Y坐标,在 (0.0,0.5)和(0.5,1.0)坐标范围内填充为(0.25, 0.75)的纹理坐标区间,如下图所示,其实我们在二分屏中使用的是(0.25,0.75)这个区间内的纹理坐标。
为什么要使用(0.25,0.75)这个区间的纹理呢?
我这里是按一般情况来考虑的,也可以使用(0.15,0.65)这种的范围,根据自己的需求定吧,如果要使用(0.15,0.65),在计算的时候(0,0.5)区间内y坐标就要加上0.15,(0.5,1.0)区间内y坐标就要减去0.35。
GLSL实现代码如下,我这里加了注释,但是运行的时候最好删除中文注释,不然有可能会报错。
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
void main(void){
vec2 uv = TextureCoordsVarying.xy;
//判断坐标范围
if(uv.y >= 0.0 && uv.y <= 0.5){
//(0.0,0.5)->(0.5, 0.75)
uv.y = uv.y + 0.25;
}else{
// (0.5,1.0)->(0.5, 0.75)
uv.y = uv.y - 0.25;
}
vec4 mask = texture2D(Texture,uv);
gl_FragColor = vec4(mask.rgb,1.0);
}
三分屏滤镜实现
需要实现的效果如下
实现思路:
和上面的二分屏类似,我们要填充的y坐标的纹理区间是(1.0/3.0,2.0/3.0),所以在(0,1.0/3.0)区间内的纹理坐标要加上1.0/3.0,在(1.0/3.0,2.0/3.0)区间内的纹理坐标不需要修改,在(2.0/3.0,1)区间内的纹理坐标要减去1.0/3.0.
GLSL代码如下:
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
void main(void){
vec2 uv = TextureCoordsVarying.xy;
if(uv.y >= 0.0 && uv.y <= 1.0/3.0){
uv.y = uv.y + 1.0 / 3.0;
}else if(uv.y >= 2.0 / 3.0){
uv.y = uv.y - 1.0/ 3.0 ;
}
vec4 mask = texture2D(Texture,uv);
gl_FragColor = vec4(mask.rgb,1.0);
}
四分屏滤镜实现
需要实现的效果如下:
实现思路: 可以看到我们缩放了图片,图片的宽度和高度都变成了原来的一半。那么怎么缩放呢?
先从Y坐标来看,分成了两个区间(0,0.5)和(0.5,1),要填充的纹理区间是(0,1),所以当uv.y <= 0.5 时,uv.y * 2 就表示区间(0,1),uv.y >= 0.5时, (uv.y - 0.5) * 2 表示区间(0,1)
同理,X坐标要填充的纹理区间也是(0,1),计算方式和计算y坐标一样。
GLSL代码如下:
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
void main(void){
vec2 uv = TextureCoordsVarying.xy;
if(uv.y <= 0.5){
uv.y = uv.y * 2.0;
}else{
uv.y = (uv.y - 0.5) * 2.0 ;
}
if(uv.x <= 0.5){
uv.x = uv.x * 2.0;
}else{
uv.x = (uv.x - 0.5) * 2.0 ;
}
gl_FragColor = texture2D(Texture,uv);
}
九分屏滤镜实现
需要实现的效果如下:
实现思路: 其实这个和上面的四分屏实现思路是一样的,只不过这里是把图片缩小了1/3。
同理,从Y坐标来看,分为三个区间,(0,3/1 ), (3/1, 2/3), (3/2 , 1)
- uv.y <= 1.0/3.0时, uv.y = uv.y * 3
- uv.y 在1.0/3.0到2.0/3.0之间时, uv.y = (uv.y - 1.0/3.0) * 3
- uv.y >= 2.0/3.0时, uv.y = (uv.y - 2.0/3.0) * 3
GLSL代码如下:
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
void main(void){
vec2 uv = TextureCoordsVarying.xy;
if(uv.y >= 0.0 && uv.y <= 1.0/3.0){
uv.y = uv.y * 3.0;
}else if(uv.y > 2.0 /3.0){
uv.y = (uv.y - 2.0 / 3.0) * 3.0 ;
}else{
uv.y = (uv.y - 1.0 / 3.0) * 3.0 ;
}
if(uv.x >= 0.0 && uv.x <= 1.0/3.0){
uv.x = uv.x * 3.0;
}else if(uv.x > 2.0 /3.0){
uv.x = (uv.x - 2.0 / 3.0) * 3.0 ;
}else{
uv.x = (uv.x - 1.0 / 3.0) * 3.0 ;
}
gl_FragColor = texture2D(Texture,uv);
}
总结
以上就是使用OpenGL ES实现的几种常见的分屏滤镜效果,理解后可自行实现不同的分屏效果,比如六分屏,横向三分屏等。
Demo地址: 分屏滤镜处理