零. 前言
分屏滤镜是指在一个有限的区域内,将内容分割为若干个部分,应用在一些剪辑或者连麦展示效果上,做了个小demo,效果如下:
一. 分屏原理
分屏滤镜修改的是片段着色器,对于同一个渲染内容,可以分成若干个模块,对于某个模块来说,需要对原纹理进行采样,采样可以选择保持原比例不裁剪,或者居中裁剪。
但是如果该模块比例发生变化的话,保持比例裁剪就会产生压缩问题,比如上面的二分屏和三分屏。
下面分别给出了将x或y坐标二等分或三等分的方法,
二等分不裁剪:左半边将坐标 * 2,由[0, 0.5]区间变为[0, 1];右半边由[0.5, 1],变为[0, 1]。
二等分裁剪:左右半边均变为[0.25, 0.75]。
三等分不裁剪:和二等分类似,直接 * 3变为[0, 1]。
三等分裁剪:均变为[1 / 3, 2 / 3]。
float splitTwoCoor(float coor, bool centerCrop) {
float res;
if (centerCrop) {
if (coor < 0.5) {
res = coor + 0.25;
}
else {
res = coor - 0.25;
}
} else {
if (coor < 0.5) {
res = coor * 2.0;
}
else {
res = (coor - 0.5) * 2.0;
}
}
return res;
}
float splitThreeCoor(float coor, bool centerCrop) {
float res;
if (centerCrop) {
if (coor < 1.0 / 3) {
res = coor + 1.0 / 3;
}
else if (coor > 2.0 / 3) {
res = coor - 1.0 / 3;
}
else {
res = coor;
}
} else {
if (coor < 1.0 / 3) {
res = coor * 3.0;
}
else if (coor < 2.0 / 3) {
res = (coor - 1.0 / 3) * 3.0;
}
else {
res = (coor - 2.0 / 3) * 3.0;
}
}
return res;
}
二. 各等分的调用
二等分:将y坐标二等分
fragment float4
twoScreenSplitFragment(SingleInputVertexIO input [[ stage_in ]],
constant bool ¢erCrop [[ buffer(0) ]],
texture2d texture [[ texture(0) ]]) {
float currentY = input.textureCoordinate.y;
float sampleY = splitTwoCoor(currentY, centerCrop);
constexpr sampler s;
float4 color = texture.sample(s, float2(input.textureCoordinate.x, sampleY));
return color;
}
三等分:将y坐标三等分
fragment float4
threeScreenSplitFragment(SingleInputVertexIO input [[ stage_in ]],
constant bool ¢erCrop [[ buffer(0) ]],
texture2d texture [[ texture(0) ]]) {
float currentY = input.textureCoordinate.y;
float sampleY = splitThreeCoor(currentY, centerCrop);
constexpr sampler s;
float4 color = texture.sample(s, float2(input.textureCoordinate.x, sampleY));
return color;
}
四等分:将x、y坐标二等分
fragment float4
fourScreenSplitFragment(SingleInputVertexIO input [[ stage_in ]],
constant bool ¢erCrop [[ buffer(0) ]],
texture2d texture [[ texture(0) ]]) {
float currentX = input.textureCoordinate.x;
float currentY = input.textureCoordinate.y;
float sampleX = splitTwoCoor(currentX, centerCrop);
float sampleY = splitTwoCoor(currentY, centerCrop);
constexpr sampler s;
float4 color = texture.sample(s, float2(sampleX, sampleY));
return color;
}
九等分:将x、y坐标三等分
fragment float4
nineScreenSplitFragment(SingleInputVertexIO input [[ stage_in ]],
constant bool ¢erCrop [[ buffer(0) ]],
texture2d texture [[ texture(0) ]]) {
float currentX = input.textureCoordinate.x;
float currentY = input.textureCoordinate.y;
float sampleX = splitThreeCoor(currentX, centerCrop);
float sampleY = splitThreeCoor(currentY, centerCrop);
constexpr sampler s;
float4 color = texture.sample(s, float2(sampleX, sampleY));
return color;
}
三. 总结
本文主要介绍了分屏滤镜的原理,在业务的分屏滤镜中,可能有各种各样的样式要求,比如左半边展示一个大头像,右半边再四等分...这些都是可以通过修改片段着色器来实现的,其原理是在特定的区域按取样公式对整个纹理进行采样,从而达到分屏的效果。
四. 参考文章
OpenGL ES(九)-自定义滤镜(分屏滤镜)