OpenGLES(八)-GLSL案例:分屏滤镜原理
效果图
本文中着重介绍glsl的分屏逻辑,对于iOS端的代码就省略了。如果对这部分有兴趣跳转OpenGLES(五)- ESLS案例:纹理贴图
顶点着色器
代码语言:javascript复制attribute vec4 position;
attribute vec2 texCoord;
varying lowp vec2 varyTexCoord;
void main(void){
gl_Position = position;
varyTexCoord = texCoord;
}
片元着色器
对于分屏功能,最重要的就是顶点坐标和纹素的获取关系;也就是对于分屏滤镜算法的理解。
二分屏
- 图中的数字都是纹理坐标
- 左图中的红线代表了二分屏后的展示内容
- 图中展示就是通过运算将原图中的纹理坐标,转换成目标图中的纹理坐标
认真观察两张图的坐标关系:
- 转换前原坐标(0.25,0),(0.75,0)-> 转换后纹理坐标(0,0),(0.5,0)
- 转换前(0.25,0),(0.75,0)-> 转换后(0.5,0),(1,0)
- 转换前(0.25,1),(0.75,1)-> 转换后(0,1),(0.5,1)
- 转换前(0.25,1),(0.75,1)-> 转换后(0.5,1),(1,1)
这种会涉及到一个简单的算法,具体看片元着色器中的处理:
代码语言:javascript复制precision highp float;
varying lowp vec2 varyTexCoord;
uniform sampler2D colorMap;
void main(void){
vec2 temp = varyTexCoord;
if (temp.x <= 0.5) {
temp.x = temp.x 0.25;
}else{
temp.x = temp.x - 0.25;
}
gl_FragColor = texture2D(colorMap, temp);
}
这里的计算不考虑顶点坐标,完全就是纹理坐标的映射关系。只需考虑在某一个纹理位置,你想要显示哪个坐标的纹素。
四分屏
因为4分屏中的每一部分都是完成的纹理图片,所以在计算上会略有不同。
坐标关系就不一一举例。
代码语言:javascript复制precision highp float;
varying lowp vec2 varyTexCoord;
uniform sampler2D colorMap;
void main(void){
vec2 temp = varyTexCoord;
if(temp.x <= 0.5){
temp.x = temp.x * 2.0;
}else{
temp.x = (temp.x - 0.5) * 2.0;
}
if(temp.y <= 0.5){
temp.y = temp.y * 2.0;
}else{
temp.y = (temp.y - 0.5) * 2.0;
}
gl_FragColor = texture2D(colorMap, temp);
}
剩下的部分大同小异,都可以通过这种画图的方式来寻找思路,这里直接放出五分屏
、九分屏
的代码。
五分屏
代码语言:javascript复制precision highp float;
varying lowp vec2 varyTexCoord;
uniform sampler2D colorMap;
void main(void){
vec2 temp = varyTexCoord;
if(temp.x <= 0.5) {
temp.x = temp.x * 2.0;
}else{
temp.x = (temp.x - 0.5) * 2.0;
}
if(temp.y <= 0.5) {
temp.y = temp.y * 2.0;
}else{
temp.y = (temp.y - 0.5) * 2.0;
}
if((varyTexCoord.x >= 0.25 && varyTexCoord.x <= 0.75) && (varyTexCoord.y >= 0.25 && varyTexCoord.y <= 0.75)){
temp = vec2((varyTexCoord.x - 0.25) * 2.0,(varyTexCoord.y - 0.25) * 2.0);
}
gl_FragColor = texture2D(colorMap, temp);
}
九分屏
代码语言:javascript复制precision highp float;
varying lowp vec2 varyTexCoord;
uniform sampler2D colorMap;
void main(void){
vec2 temp = varyTexCoord;
if(temp.x <= 1.0 / 3.0){
temp.x = temp.x 1.0 / 3.0;
}else if(temp.x >= 2.0 / 3.0){
temp.x = temp.x - 1.0 / 3.0;
}
if(temp.y <= 1.0 / 3.0){
temp.y = temp.y 1.0 / 3.0;
}else if(temp.y >= 2.0 / 3.0){
temp.y = temp.y - 1.0 / 3.0;
}
gl_FragColor = texture2D(colorMap, temp);
}
总计
简单总结一下,想要完成这种类似的滤镜效果就是要通过观察找到变换的规律,然后通过对纹理坐标的计算来完成滤镜效果。个人理解就是:找到几个关键点,然后思考这些点具体需要展示的纹素是什么,从而完成计算.