- iOS视觉-- (08) OpenGL ES+GLSL实现分屏滤
- iOS视觉-- (06) OpenGL ES+GLSL实现灰度滤
- iOS视觉-- (10) OpenGL ES+GLSL实现YUV
- iOS视觉-- (07) OpenGL ES+GLSL实现多滤镜
- iOS视觉-- (11) OpenGL ES+GLSL实现大眼和
- iOS视觉-- (12) OpenGL ES+GLSL实现口红和
- iOS视觉-- (09) OpenGL ES+GLSL实现摄像头
- OpenGL ES案例-实现分屏滤镜
- iOS视觉-- (04) OpenGL ES+GLSL实现金字塔
- iOS视觉-- (05) OpenGL ES+GLSL实现正方体
通过前一篇我们学习了图片灰色滤镜,上一篇图片多滤镜。滤镜的实现其实就是对着色器进行编程,把渲染管线封装好,替换着色器就可以了。
少废话,先看效果Demo
-
二分屏

注意⚠️:着色器中最好不要写中文注释,有可能编译不成功,这里主要是为了便于理解
- 左右二分屏着色器代码:
precision mediump float; //通过precision关键字来指定默认精度,这样就不用每一个变量前面都声明精度限定符了
varying lowp vec2 varyTextCoord; //顶点着色器传递过来的纹理坐标
uniform sampler2D colorMap; //纹理
void main()
{
//利用一个临时的二维向量,获取到纹理坐标
vec2 uv = varyTextCoord.xy;
float x;
if (uv.x >= 0.0 && uv.x <= 0.5) {
// 将x坐标的值映射为0.25~0.75
x = uv.x + 0.25;
} else {
x = uv.x - 0.25;
}
//获取纹素
gl_FragColor = texture2D(colorMap, vec2(x, uv.y));
//由于y的值没有变,不需要再设y的值
}
分析:原理:1.先找到显示范围 --->2.确定映射关系
通过前面的学习,我们知道纹理左边是由左下角(0,0)到右上角(1,1),构成的,如下图:

1.先找到显示范围:人物大概在0.25~0.75的位置,所以映射时就从纹理X轴的0.25位置开始,到0.75结束,如下图:

2.确定映射关系
所以左边屏幕就是:
x = uv.x + 0.25;
那么右边的屏幕就是:
x = uv.x - 0.25;
(意思就是:右边屏幕也要映射纹理0.25~0.75)这里刚好是4份,比较特殊;
比方说:如果需要显示的区域从左边的风车开始,大约就是0.1,那么加上屏幕的一半(0.5),最大的X轴就是0.6。
所以左边屏幕就是:x = uv.x + 0.1;
那么右边的屏幕就是:x = uv.x - 0.4;
效果图
那么上下二分屏大家应该也知道怎么算了。人脸的范围大概在Y轴的(0.45~0.95),如下图

- 上下二分屏着色器代码:
void main()
{
//利用一个临时的二维向量,获取到纹理坐标
vec2 uv = varyTextCoord.xy;
float y;
if (uv.y >= 0.0 && uv.y <= 0.5) {
// 将Y坐标的值映射为0.45~0.95
y = uv.y + 0.45;
} else {
y = uv.y - 0.05;
}
//获取纹素
gl_FragColor = texture2D(colorMap, vec2(uv.x, y));
//由于X的值没有变,不需要再设y的值
}
-
三分屏
上面学习了二分屏,那么三分屏也是这样的,过程就不解析了。把屏幕分成三份,找到显示范围,确定映射关系就OK了。
- 三分屏着色器代码:
precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;
void main() {
vec2 uv = varyTextCoord.xy;
if (uv.y >= 0.0 && uv.y < 1.0/3.0) {
//下边
uv.y = uv.y + 2.0/3.0 - 0.05;
} else if(uv.y >2.0/3.0){
//上边
uv.y = uv.y - 0.05;
} else {
//中间
uv.y = uv.y + 1.0/3.0 - 0.05;
}
gl_FragColor = texture2D(colorMap, uv);
}
-
四分屏

本来这块正方形是显示一张图片,现在感觉是显示了4张图片,就好像是把纹理缩小到四分之一的大小
- 四分屏片元着色器代码:
precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;
void main(){
vec2 uv = varyTextCoord.xy;
if (uv.x <= 0.5) {
uv.x = uv.x * 2.0;
} else {
uv.x = (uv.x - 0.5) * 2.0;
}
if (uv.y <= 0.5) {
uv.y = uv.y * 2.0;
} else {
uv.y = (uv.y - 0.5) * 2.0;
}
gl_FragColor = texture2D(colorMap, uv);
}
代码中的意思就是X轴,Y轴各缩小2倍。有的同学肯定会问,为什么是乘以2呢?不应该是除以2吗?我们把上面的代码通过临时变量来看就比较清楚一点,如下
precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;
void main(){
vec2 uv = varyTextCoord.xy;
float a; //新的纹理坐标X值
float b = uv.x; //原来的纹理坐标X值
if (b <= 0.5) {
a = b * 2.0;
} else {
a = (b - 0.5) * 2.0;
}
uv.x = a;
if (uv.y <= 0.5) {
uv.y = uv.y * 2.0;
} else {
uv.y = (uv.y - 0.5) * 2.0;
}
gl_FragColor = texture2D(colorMap, uv);
}
因为我们要屏幕的一半显示完X轴、Y轴,设纹理X轴为b,Y轴为A,那么关系就如图下所示:
四分屏
六分屏和九分屏原理和四分屏类似,只贴代码
-
六分屏
precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;
void main(){
vec2 uv = varyTextCoord.xy;
if (uv.x <= 0.5) {
uv.x = uv.x * 2.0;
} else {
uv.x = (uv.x - 0.5) * 2.0;
}
if (uv.y <= 1.0/3.0) {
uv.y = uv.y * 3.0;
} else if(uv.y > 1.0/3.0 && uv.y <= 2.0/3.0) {
uv.y = (uv.y - 1.0/3.0) * 3.0;
}else{
uv.y = (uv.y - 2.0/3.0) * 3.0;
}
gl_FragColor = texture2D(colorMap, uv);
}
-
九分屏
precision highp float;
uniform sampler2D colorMap;
varying highp vec2 varyTextCoord;
void main(){
vec2 uv = varyTextCoord.xy;
if (uv.x <= 1.0/3.0) {
uv.x = uv.x * 3.0;
} else if(uv.x > 1.0/3.0 && uv.x <= 2.0/3.0) {
uv.x = (uv.x - 1.0/3.0) * 3.0;
}else{
uv.x = (uv.x - 2.0/3.0) * 3.0;
}
if (uv.y <= 1.0/3.0) {
uv.y = uv.y * 3.0;
} else if(uv.y > 1.0/3.0 && uv.y <= 2.0/3.0) {
uv.y = (uv.y - 1.0/3.0) * 3.0;
}else{
uv.y = (uv.y - 2.0/3.0) * 3.0;
}
gl_FragColor = texture2D(colorMap, uv);
}
网友评论