Android 实现抖音传送带特效

本文介绍了如何利用OpenGLES中的Fbo技术实现抖音传送带特效,通过分析纹理坐标和Fbo的保留帧功能,展示了如何在预览画面中模拟边缘区域的连续移动。同时提供了Java代码实现的部分细节和Android核心知识点的学习资源链接。
摘要由CSDN通过智能技术生成
1.2 笔者实现传送带特效

从上图来看,笔者实现的效果基本上和抖音实现的一致

那么,对于该特效,我们应该如何去实现呢?

其实在介绍抖音蓝线挑战特效那一章已经将到一个核心知识点Fbo,对,没错,当时做蓝线挑战特效用到的就是Fbo,接下来传送带特效也需要使用Fbo的保留上一帧功能

接下来,我们就来进行特效分析和具体实现

二、特效分析


首先,根据上面的效果图,我们可以简单画出示意图,如下图所示(小格子的数量越多,画面越精细)

我们以横向进行分析

OpenGLES中,纹理坐标水平方向的起始位置在左方(准确的说是在左上角,这里只是分析横向的效果,故图上标点0.0随意标在左方,便于分析) 根据上面的效果图,了解到,该特效有两个特点

  • 屏幕左半边部分是正常预览视频

  • 屏幕右半边部分像传送带一般,将画面不断地像右边运送

这里,我用了运送一词,那么,我们得首先知道,它运送的是什么

2.1 运送什么?

通过分析特效图,我们知道,图像右半部分是不断地向右边移动,而左半部分是正常预览的,看起来就好像是从左半部分的边缘处不断移动到右边,那么从这里可以得出一个小结论

它运送的是左半部分的边缘区域,根据上图,准确的说是中线左边0区域的画面

那么,知道了这点,我们就一目了然了

2.2 它是如何运送的?

前面,我们知道了它运送的是0区域的画面,那么接下来就来分析下,它是如何运送的

  • 在预览时,相机画面一般都是正常显示,0区域的画面当然也是正常一帧帧刷新

  • 当0区域显示第一帧(简称f1,后面以f开后,数字为帧序)时,将其移动到1区域

  • 当0区域显示f2时,将1区域的f1移动到2区域,将0区域的f2移动到1区域

  • 依次类推,就可以将0区域的画面源源不断地运送到右边

2.3 Fbo

其实,在知道了它是运送什么,且如何运送后,我们还是无法得知如何实现这一特效

此刻,就该Fbo登场了,前面蓝线挑战特效的篇章已经对其做了详细描述,现在简单介绍下

  • 可以将Oes纹理转换成2D纹理

  • 可以将纹理数据不显示在屏幕上,并保留下来

这里,我们要实现该特效,就要使用它的保留帧数据的功能

2.4 特效实现

在上面,我们已经知道了该特效是如何运送数据,那么通过下图,我们来了解如何使用Fbo实现图片

从上面的分析可知,该特效运送的是左半部分的边缘区域,所有有如何下实现步骤:

  • 首先假设每个小格的步长为0.1,那么左半部分的边缘区域就是0.4 ~ 0.5这个区域

  • Fbo可以保存上一帧,那么在渲染时,我们将上一帧的数据保存下来

  • 在渲染的时候,会有两个纹理,一个是相机的正常预览纹理,另一个是保存的上一帧,此时,我们在着色器里就要进行判断

  • 当纹理坐标x小于0.5时,显示相机的正常预览画面

  • 当纹理坐标x大于0.5时,显示保存的上一帧画面,不过这里要注意,并不是对应坐标的上一帧数据,即,不是0.5 ~ 1.0区域的数据,而是0.4 ~ 0.9区域的数据,大家可以思考下这是为什么,后面具体实现的时候会有解答

这样,当相机不断产生预览数据时,右半部分将不断地将左半部分的边缘区域向右边运送

三、具体实现


前面我们分析了该特效的整个实现流程,接下来就是具体的实现

首先,先上大家最关心的着色器代码

3.1 着色器

顶点着色器

attribute vec4 aPos;

attribute vec2 aCoordinate;

varying vec2 vCoordinate;

void main(){

vCoordinate = aCoordinate;

gl_Position = aPos;

}

关于顶点着色器,并没有做任何特殊处理 片元着色器

precision mediump float;

uniform sampler2D uSampler;

uniform sampler2D uSampler2;

varying vec2 vCoordinate;

uniform float uOffset;

void main(){

if (vCoordinate.x < 0.5) {

gl_FragColor = texture2D(uSampler, vCoordinate);

} else {

gl_FragColor = texture2D(uSampler2, vCoordinate - vec2(uOffset, 0.0));

}

}

对于片元着色器,关键就在于main()函数里面的if判断,前面也有提到,会对纹理坐标进行一个判断

  • 当x小于0.5时,显示相机预览画面

  • 当x大于0.5时,显示上一帧的数据,且取的是对应坐标往左偏移的数据(uOffset是偏移量,可以理解成小格子的宽度)

那么对于为什么要偏移呢?

这是因为通过上面,我们可以知道,该特效是从左半部分的边缘区域开始运送的,那么如果我们从对应坐标取,那么不就得不到左半部分区域的坐标了吗,所有得偏移一个小格子的宽度,从而得到对应的数据 这样,每帧渲染时,都取0.4 ~ 0.9区域数据显示到0.5 ~ 1.0区域,从而就实现了该传送带特效

在知道了如何实现该特效后,我们还可以实现纵向的传送带特效,只需要将片元着色器里的x改为y即可

precision mediump float;

uniform sampler2D uSampler;

uniform sampler2D uSampler2;

varying vec2 vCoordinate;

uniform float uOffset;

void main(){

if (vCoordinate.y < 0.5) {

gl_FragColor = texture2D(uSampler, vCoordinate);

} else {

gl_FragColor = texture2D(uSampler2, vCoordinate - vec2(0.0, uOffset));

}

}

3.2 Java代码实现部分

下面是Java代码实现部分

Android核心知识点

面试成功其实是必然的,因为我做足了充分的准备工作,包括刷题啊,看一些Android核心的知识点,看一些面试的博客吸取大家面试的一些经验。

下面这份PDF是我翻阅了差不多3个月左右一些Android大博主的博客从他们那里取其精华去其糟泊所整理出来的一些Android的核心知识点,全部都是精华中的精华,我能面试到现在2-2资深开发人员跟我整理的这本Android核心知识点有密不可分的关系,在这里本着共赢的心态分享给各位朋友。

不管是Android基础还是Java基础以及常见的数据结构,这些是无原则地必须要熟练掌握的,尤其是非计算机专业的同学,面试官一上来肯定是问你基础,要是基础表现不好很容易被扣上基础不扎实的帽子,常见的就那些,只要你平时认真思考过基本上面试是没太大问题的。

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上我搜集整理的2019-2021BAT 面试真题解析,我把大厂面试中常被问到的技术点整理成了PDF,包知识脉络 + 诸多细节。

节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

常被问到的技术点**整理成了PDF,包知识脉络 + 诸多细节。

节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值