OpenGL ES分屏滤镜-静态分屏

2020-08-10  本文已影响0人  Joker_King

静态分屏是指每一个屏幕的图像都完全一样。

分屏滤镜实现原理是在片元着色器中修改纹理坐标和纹理的对应关系。分屏之后,每个屏内纹理的对应关系都不一样。

这里我们用一种通用的方式来实现分屏滤镜,将屏数交由外部来控制。

预备知识

首先,我们来了解等一下会使用到的 GLSL 运算和函数。vec2 是二维向量类型,它支持下面的各种运算。

向量与向量的加减乘除(两个向量需要保证维数相同)

下面以乘法为例,其他类似。

vec2 a, b, c;
c = a * b;

等价于

c.x = a.x * b.x;
c.y = a.y * b.y;

向量与标量的加减乘除

下面以加法为例,其他类似。

vec2 a, b;
float c;
b = a + c;

等价于

b.x = a.x + c;
b.y = a.y + c;

向量与向量的 mod 运算(两个向量需要保证维数相同)

vec2 a, b, c;
c = mod(a, b);

等价于

c.x = mod(a.x, b.x);
c.y = mod(a.y, b.y);

向量与标量的 mod 运算

vec2 a, b;
float c;
b = mod(a, c);

等价于

b.x = mod(a.x, c);
b.y = mod(a.y, c);

着色器实现

有了上面的 GLSL 运算知识,来看下我们最终实现的片元着色器。

precision highp float;

uniform sampler2D inputImageTexture;
varying vec2 textureCoordinate;

uniform float horizontal;  // (1)
uniform float vertical;

void main (void) {
   float horizontalCount = max(horizontal, 1.0);  // (2)
   float verticalCount = max(vertical, 1.0);
 
   float ratio = verticalCount / horizontalCount;  // (3)
   
   vec2 originSize = vec2(1.0, 1.0);
   vec2 newSize = originSize;
   
   if (ratio > 1.0) {
       newSize.y = 1.0 / ratio;
   } else { 
       newSize.x = ratio;
   }
   
   vec2 offset = (originSize - newSize) / 2.0;  // (4)
   vec2 position = offset + mod(textureCoordinate * min(horizontalCount, verticalCount), newSize);  // (5)
   
   gl_FragColor = texture2D(inputImageTexture, position);  // (6)
}

下面简单演示一下每一步计算的效果,帮助理解:


image
上一篇下一篇

猜你喜欢

热点阅读