美文网首页iOS学习开发
音视频开发 - 分屏滤镜

音视频开发 - 分屏滤镜

作者: 文艺女青年的男人 | 来源:发表于2019-10-24 17:18 被阅读0次

在抖音等常用的音视频软件中经常发现有分屏的滤镜效果,现在总结一下具体的VertexShader中,每个函数中的算法。

常规方法滤镜中的FragmentShader算法

vertexShader代码设置

attribute vec4 Position;   
attribute vec2 TextureCoords;
varying vec2 TextureCoordsVarying;

void main (void) {
    gl_Position = Position;
    TextureCoordsVarying = TextureCoords;
}

其中Position是我们的物体坐标,TextureCoords是纹理坐标,TextureCoordsVarying是我们需要传递到FragmentShader中的纹理坐标值,下面是FragmentShader中的内容

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;

void main (void) {
    vec4 mask = texture2D(Texture, TextureCoordsVarying);
    gl_FragColor = vec4(mask.rgb, 1.0);
}

需要注意的是在顶点着色其中的数据类型默认是有精度值得,但是在片元着色器中是没有设置精度的,所以我们需要为float设置精度precision highp float;

分析片元着色器中的赋值,首先根据纹理ID和纹理坐标获取纹理像素值mask,将mask进行4维向量转化,其目的是设置1.0的透明度,这里设置的不透明的,也可以直接将mask赋值给gl_FragColor,查看这样算法的效果。


默认渲染纹理
二屏滤镜中的FragmentShader算法

我们默认是读取图片的中间部分,y轴方向是0.25-0.75,x轴方向0.0-1.0,所以我们在FragmentShader算法中进行修改。

precision highp float;
uniform sampler2D Texture;
varying highp vec2 TextureCoordsVarying;

void main() {
    vec2 uv = TextureCoordsVarying.xy;
    float y;
    if (uv.y >= 0.0 && uv.y <= 0.5) {
        y = uv.y + 0.25;
    } else {
        y = uv.y - 0.25;
    }
    gl_FragColor = texture2D(Texture, vec2(uv.x, y));
}

其中我们获取传递过来的纹理坐标的xy,然后对当前二维向量y值进行重新设置:
当y在uv.y >= 0.0 && uv.y <= 0.5,在y轴方向我们其实应该获取的是屏幕中间部分,所以y = uv.y + 0.25,将y方向上的纹理进行重新设置,读取从0.25 - 0.75的数据。
当0.5-1.0时,在y轴防线我们-0.25,获取从0.25 - 0.75的数据,效果如下。


二屏滤镜
三屏滤镜中的FragmentShader算法

我们默认是读取图片的中间1/3部分,y轴方向是1/3-2/3,x轴方向0.0-1.0,所以我们在FragmentShader算法中进行修改。

precision highp float;
uniform sampler2D Texture;
varying highp vec2 TextureCoordsVarying;

void main() {
    vec2 uv = TextureCoordsVarying.xy;
    if (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;
    }
    gl_FragColor = texture2D(Texture, uv);
}

其中我们获取传递过来的纹理坐标的xy,然后对当前二维向量y值进行重新设置:
当y在uv.y < 1.0/3.0,在y轴方向我们其实应该获取的是屏幕中间1/3部分,所以uv.y = uv.y + 1.0/3.0,将y方向上的纹理进行重新设置,读取从1/3 - 2/3的数据。
当uv.y > 2.0/3.0时,在y轴防线我们- 1.0/3.0,获取从1/3 - 2/3的数据,效果如下。
其他的区域默认是不变的。
效果如下


三屏滤镜
四屏滤镜中的FragmentShader算法

我们默认是将整张图片进行压缩,将这张压缩图放到屏幕均分的四个位置,所以我们在FragmentShader算法中进行修改。

precision highp float;
uniform sampler2D Texture;
varying highp vec2 TextureCoordsVarying;

void main() {
    vec2 uv = TextureCoordsVarying.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(Texture, uv);
}

其中我们获取传递过来的纹理坐标的xy,然后对当前二维向量x和y值进行压缩之后重新设置:
在x方向,当uv.x <= 0.5,我们将原始的x进行放大2倍,那么新的x获取到的就是原始纹理2倍x出的纹理像素值;在0.5-1.0,我们需要将原始x-0.5,在进行放大2倍,这样我们就将x方向纹理像素值缩小后后放到了新的x位置;
同理y轴方向进行缩放;效果如下


si屏滤镜
六屏滤镜中的FragmentShader算法

我们默认是读取图片的中间矩形部分,y轴方向是1/3-2/3,x轴方向1/3-2/3,所以我们在FragmentShader算法中进行修改。

precision highp float;
uniform sampler2D Texture;
varying highp vec2 TextureCoordsVarying;

void main() {
    vec2 uv = TextureCoordsVarying.xy;
   
    if(uv.x <= 1.0 / 3.0){
        uv.x = uv.x + 1.0/3.0;
    }else if(uv.x >= 2.0/3.0){
        uv.x = uv.x - 1.0/3.0;
    }
    
    if(uv.y <= 0.5){
        uv.y = uv.y + 0.25;
    }else {
        uv.y = uv.y - 0.25;
    }
    
    
    gl_FragColor = texture2D(Texture, uv);
}

其中我们获取传递过来的纹理坐标的xy,然后对当前二维向量x、y值进行重新设置:
当x方向,在uv.x <= 1.0 / 3.0,我们获取的应该是从1/3开始的纹理,所以+1/3,在uv.x >= 2.0/3.0时,还是取1/3开始的纹理,所以应该-1/3;
在y轴方向,我们取0.25-0.75两部分,y轴展示时我们可以分成0-0.5和0.5-1.0两部分,所以当uv.y <= 0.5,应该+0.25,在其他位置-0.25;
效果如下


屏幕快照 2019-10-24 下午5.16.09.png
总结

我们只是提供了一种算法的思路,具体的业务变化需要我们灵活的变动相应的算法,来适应不同的业务需要

欢迎关注我的公众号,专注iOS开发、大前端开发、跨平台技术分享。


iOS开发之家

相关文章

  • 音视频开发 - 分屏滤镜

    在抖音等常用的音视频软件中经常发现有分屏的滤镜效果,现在总结一下具体的VertexShader中,每个函数中的算法...

  • 08-OpenGL ES 分屏滤镜

    分屏滤镜分析 分屏滤镜 - 分2屏 分屏滤镜 - 分4屏 案例-分屏滤镜导图 源码链接 https://githu...

  • OpenGL ES之滤镜处理(2)_灰度滤镜与马赛克滤镜

    上文 OpenGL ES之滤镜处理(1)_分屏滤镜 - 简书讲述了分屏滤镜的处理,本文介绍灰度滤镜与马赛克滤镜的处...

  • OpenGL ES(九)-自定义滤镜(分屏滤镜)

    分屏滤镜(2) 顶点着色器源码: 片元着色器源码: 分屏滤镜(3) 顶点着色器不变片元着色器源码: 分屏滤镜(4)...

  • OpenGL ES案例-实现分屏滤镜

    分屏滤镜在现在的短视频中十分常见,今天我们就使用OpenGL ES来实现分屏滤镜的效果。 一、实现结果 二、分屏原...

  • 分屏滤镜

    vertShader fragShader 2分屏 3分屏 4分屏 6分屏 9分屏

  • 如何优雅地实现一个分屏滤镜

    本文通过编写一个通用的片段着色器,实现了抖音中的各种分屏滤镜。另外,还讲解了延时动态分屏滤镜的实现。 一、静态分屏...

  • 滤镜

    1.分屏 分屏的实现思路就是调整顶点坐标与纹理坐标的映射关系 2.灰色滤镜 灰色滤镜有5种实现方案,都是取比例颜色...

  • OpenGL 分屏滤镜

    1

  • 0016--滤镜:分屏滤镜

    [toc] 前言 通过自定义着色器实现分屏滤镜功能. 准备工作 导入相关头文件 FilterBar为一个选择Bar...

网友评论

    本文标题:音视频开发 - 分屏滤镜

    本文链接:https://www.haomeiwen.com/subject/axigyctx.html