本文依据「大表姐」李阳(Cocos 引擎布道师负责人)于 2021 年 6 月 26 日举办的 ECUG Meetup 第 1 期 | 2021 音视频技术最佳实际·杭州站上的分享整顿而成。本文长达 5800 余字,次要构造如下:
- Cocos 引擎介绍
- Cocos Creator && Engine
- 基于 FFmpeg 的 Cocos Creator 视频播放器
- Cocos 的音视频播放及革新
获取「讲师完整版 PPT」,请增加 ECUG 小助手微信(微信 ID:ECUGCON)并备注「ECUG PPT」。其余讲师的分享也将于后续陆续放出,敬请期待。
以下为分享注释:
大家伙,我是 Cocos 引擎布道师负责人李阳。我写了大略七年的代码,始终是做基于 Cocos 引擎的手游研发,做的可能被大家相熟的一款游戏是捕鱼达人。
我当初在 Cocos 做布道师负责人,在我看来这个职业就 是开发者的辅助师、技术的导航仪,次要是帮助用公司引擎的开发者更高效地开发出游戏,帮忙他们解决技术上的问题,提供引擎部门的反对。
一、Cocos 引擎介绍
Cocos 以「技术驱动数字内容行业效率晋升」为理念。从 2011 年成立到目前为止,在寰球有 140 万个注册开发者,注销游戏数有将近 10 万。下载 Cocos 引擎制作游戏或者 APP 的大略有 16 亿设施,包含 203 个国家和地区。
上图中是 Cocos 引擎的一些市场占有率。中国手游的占有率是 40%,中国小游戏的占有率 64%,在线教育 APP 占有率是 90%。在线教育畛域 Cocos 有专门的教育编辑器,用相似 PPT 的形式就能够开发出一个互动的游戏。
上图右边是 2020 年 5 月的一些数据,右侧的是一些游戏案例。《剑与远征》不晓得大家有没有玩过,《动物餐厅》是微信小游戏的创意游戏,用户和流水过亿级别的;《世界争霸》是一个月就研发进去的游戏,当然它的团队规模也是很大的。弹无虚发这个游戏介绍最初这个游戏,它是一个只有三个人的团队开发的,程序员只有一个。所以说,咱们的引擎和编辑器是可能十分高效并且疾速地研发出游戏来。
咱们波及的方面比拟多,包含教育、车载、数字孪生、在线展会等等。包含腾讯、华为、网易等等,都是咱们的合作伙伴,都在用 Cocos 引擎进行开发。
用 Cocos 编辑器能够进行可视化编辑,能够模块实现游戏创作,展示上的所见即所得的状态。
Cocos 编辑器能够做 2D 和 3D 游戏。针对美术工作流它还有有动画编辑器,以及粒子系统等等,通过非常简单的模块化升高了游戏开发的门槛。
上图是咱们跨平台的工作流。3ds Max、Maya 是第三方软件,用于做模型;UI 和 Animation 可视化局部能够用 cocos 编辑器去做。Code IDE 去写咱们的逻辑代码。咱们能够实现所见即所得的研发体验。
二、Cocos Creator && Engine
上图则是 Cocos Creator 引擎的架构。Game Assets 是咱们的资源,Game Logic 是咱们写的代码。前面咱们会有 Cocos Creator Engine,包含渲染、Scene Graph 以及咱们的资源和数据,还有特效、物理以及组件化,UI,最初公布到平台。上面是咱们的后端渲染,Metal 对应的是苹果,Vulkan 是在安卓平台上做渲染,WebGL 是 web 端。
Cocos 引擎目前在 2D 手游局部占的比例会比拟大,但在 3D 上咱们也有很好的体现。华为海思也帮咱们实现了 提早渲染的管线,前面我会具体介绍一下,相对来说十分的实在。
咱们的引擎局部是 100% 开源的,开源引擎就在 Github 上。在编辑器还有一个偏好设计,就是说咱们下载下来会带有一个绝对应版本的引擎。然而咱们开源的局部,你能够去改咱们的引擎,在 TS Engine 和 Native C++ Engine 上抉择本人批改引擎的门路,用可定制化的引擎去做本人想要的版本。这也是咱们更加多元性和定制化,给所有的开发者减少的接口。
我略微遍及一下纹理渲染。CPU 从内存读出数据,而后把 Vertex Data 发送到 Vertex Shader,通过剪裁再到片段着色器,通过混合和测试,最初到屏幕上,这是整个的渲染流程。
Cocos Creator Renderer 中,RenderScene 治理引擎上的所有节点,FrameGraph 是数据的依赖。咱们这边有两个 Pipeline,其中一个是 Forward,前向渲染。
前向渲染会有一个什么问题呢?它是相当线性的,并且每次将每个几何图形向下通过管道一次以生成最终图像。然而模型和模型之间有一个重合的局部,比方后面有一个模型,两头有一个模型,前面还有一个模型,但其实真正摄像机看到的局部只有第一个。然而如果成像渲染的话,我会把三个都渲染一遍,但真正到可视化的时候只有一个,前面被遮挡住局部的计算是冗余的。
而在提早渲染中,着色将提早一点,直到所有几何图形都通过管道为止,生成最终图像。当顶点数据传到顶点着色器上,走到片断着色器,它会把这些数据存到 G -Buffer 上。下一阶段再把 G-Buffer 的数据再传到顶点着色器上。这个时候,顶点着色器对 G-Buffer 数据的处理程序和上一阶段的顶点着色器程序是不一样的,是两套逻辑,它的解决数据的模式是不同的。
接下来,会到片断着色器上,片断着色器是以屏幕上的像素点为单位,只会去渲染要显示在以后像素上的图形就好了,其余被遮挡的图像并不在计算范畴之内,它就会大量节俭计算的工夫。
方才咱们讲到不同平台的渲染接口,咱们做了一个 GFX 的分装。它会把这些接口变成同样一个 API,因为咱们用 GFX 这个阶段是开发者能够看到的,然而我要公布到不同平台,如果我的 API 不同,会减少开发者的工作工夫和工作量,所以咱们把它进行了封装。在开发游戏的时候,不思考平台,都是用同样一套 API,等到去公布的时候,再去构建、去抉择要用的渲染。
这是原生局部的渲染,我讲一下 GFX Agent。GFX Agent 会传一些指令到 CPU 上,如果咱们这个队列里是 20 个命令,每一帧的时候,首先咱们要读取队列,队列里的指令要执行,而后再从队列里刨进来。
然而有时候,如果整个指令过于多的状况下,失常的话咱们是 1 秒 60 帧,这是 OK。也就是这个工夫范畴内,如果我解决不完,我以后 CPU 传给 GPU 的指令就会呈现卡顿。如果我当初一帧卡顿了,导致用了两帧的工夫才实现一次渲染,那就阐明我当初的帧曾经从 60 掉到了 30,如果我卡顿用了三帧的工夫,那我就从 60 间接掉到 20 帧(以上都是实时帧率)。
依据这个问题咱们做了 GFX Agent,就是说以后的线程咱们并非是实时处理 GPU 的编码命令,咱们这个阶段只会收集并打包这些指令,咱们会放到队列里。而后我会在执行这些指令的时候另开一条线程。
线程也是有队列的,如果当我的 CPU 来不及传一些指令到 GPU 的时候(大家必定理解,卡顿大部分是 GPU 期待 CPU 的等待时间),会引起卡顿。所以当 CPU 没有把指令传到 GPU 的时候,哪怕 GPU 没收到新的指令,然而在另外开启一个线程里,还是有货色能够被渲染的,就不会引起卡顿情况。
咱们当初的版本是 Cocos CreatorV3 版本,做了一些性能的晋升:
第一,面向古代图形接口的多后端 GFX;第二,负载平衡的多线程渲染器。当我要发布命令到某些线程的时候,会对这些线程进行检测,或者说看一下哪个线程解决的工作比拟少。这时候就会把工作放到工作比拟少的线程里,会保障每个线程的工作是相对来说差不多的,维持负载平衡的情况;第三,高度可定制的渲染管线;第四,华为奉献的高性能提早渲染管线;第五,基于挪动端 TBR&TBDR GPU 的 Memoryless 架构。
因为咱们晓得,在挪动端比拟吃硬件,比如说我的量十分大的时候,挪动端传到手机上,你可能会发现有一些发热或者说接管提早的状况。TBR 它将须要渲染的画面分成一个个的区块(tile),每个区块的坐标通过两头缓冲器以列表模式保留在零碎内存中。TBDR TBDR 渲染的一个要害是提早渲染。
三、基于 FFmpeg 的 Cocos Creator 视频播放器
上面,我讲一下基于 FFmpeg 的 Cocos Creator 视频播放器,以开心猴子为例子。咱们在教育课件上会有一些互动的游戏,互动游戏必定少不了播一些视频,这时就会有一些问题。
比如说这张图,咱们是以同样一套设计,Android、IOS、Web 上的视觉效果是不统一的。并且因为 fix top 设计的限度,我是不能应用遮罩组件限定形态的,它不反对远角的覆盖。还有场景切换时会呈现一种情况,我退出了一个场景,然而我以后存在视频组件的残影,这都是在用引擎开发游戏时遇到咱们的问题。
因而,咱们的解决思路是什么?次要是分两局部:FFmpeg 和 Web Video Element。
咱们应用 FFmpeg 去做编码,再用 OpenGL 进行渲染,公布到手机上。Android 用 Oboe 去做一屏播放,IOS 用 AudioQueue 做音频上的播放。Web,咱们利用了 Video 做元素去进行解码,用 WebGL 去做视频方面的渲染,以及用 Web Audio API 去做音视频的播放。这就是咱们整体的解决方案的思路。
这是一些音频划分。首先,会用 FFmpeg 解码音视频,对 ffplay 进行了革新,做了 AVplay。解码之后,各端接入音视频的解码,Android、IOS、Web 用的都是不同的。最初,咱们有一个 jsb 绑定视频组件接口。因为咱们整个引擎是用 js 语言,然而咱们的音频播放器是用 C++ 写,所以咱们必须通过 jsb 绑定,让 js 可能去调用其余语言的对象。
前面是音频方面的播放,我方才也讲到,Android、IOS、Web 别离用的是不同的音频播放解决。最初,咱们有一个优化与扩大,比如说边下边播、精准 seek、libyuv 代替 swscale。
对这点我略微补充一下。为什么咱们要做这样的事件,是因为如果想在咱们游戏里,用引擎播放视频的话,整个框架是迁过来的,是没有方法和咱们引擎当中的一些组件去做交互的,它也没有所谓的层级关系,我没有方法对这个视频进行操作,也没有方法通过用户这边的行为去对视频做一些互动。所以这是咱们要去基于 FFmpeg 做批改的起因。因为这样的话,是等于把咱们的 video 上的每一帧全副渲染到咱们的引擎上,所以它会有一些效率上的问题,这就是咱们为什么用 libyuv 代替 swscale 的起因。
我再说一下 AVplay 革新。咱们对 FFmpeg 的源码进行了编译之后,发现有三个可执行的程序:
- 第一,FFmpeg 用于音视频视频格式转换、视频剪接等;
- 第二,ffplay 用于播放音视频,须要依赖 SDL;
- 第三,ffprobe 用于剖析音视频流媒体数据;
它有什么问题呢?尽管它是满足了咱们对于播放音视频的需要,然而它在咱们革新当中呈现一些问题,比如说它在进行纹理缩放以及像素、格局转化的时候,效率非常低,并且它不反对 AndroidSL 文件的读取,所以咱们对这个进行了革新。
这是 AVplayer 整个革新的思维路。首先,咱们会调用一个函数去初始化所有的信息,而后去创立一个 read thread 和 refresh thread。它会创立音频、视频以及字幕的解码程序。refresh thread 是对咱们传过来的比如说视频上的图片序列、音频上的样本序列以及字幕的字符串序列进行耗费。以上是 AVPlayer 的整个架构。
这是 JSB 绑定视频组件接口。JSB 绑定的起因,是为了让 JSB 去调用 C++ 的对象以及其余的语言,因为咱们的引擎语言和视频播放器的语言不是一种,所以咱们要让他们产生一个调用关系,所以咱们对 JSB 端做一个绑定。在这里咱们还做了一个分装的类,就是 Video,这是它的 UML。
做完了 JSB 的绑定,就到了渲染的局部,就是我方才说的咱们要把视频上的每一帧都渲染到咱们的引擎上,它次要就是三个步骤:
- 第一,自定义材质,材质负责着色器程序;
- 第二,自定义 Assembler,它负责传递顶点属性;
- 第三,设置材质动静参数,比如说设置纹理、变换平移旋转缩放矩阵等。
对于自定义材质,着色器程序须要写在 effect 文件中,而 effect 被 material 应用,每个渲染组件,须要挂载 material 属性。因为视频展现,能够了解为图片帧动画渲染,因而能够间接应用 Cocos Creator 提供的 CCSprite 所用的 builtin-2d-sprite 材质。
对于自定义 Assembler,有了材质后,只须要关怀地位坐标和纹理坐标传递,即要自定义 Assembler,可参考官网文档自定义 Assembler。原生端和 Web 端世界坐标计算形式(updateWorldVerts)不一样,否则会呈现展现地位错乱问题。
对于设置材质动静参数,在视频播放器中,须要动静批改的就是纹理数据了,在挪动端,ffplay 革新后的 AVPlayer 在播放过程,通过 ITextureRenderer.render 接口调用到 void Video::setImage 办法,理论在不断更新纹理数据。
以上是基于 FFmpeg 做的革新,这是咱们革新完之后的场景(图示)。方才那个视频其实曾经是咱们渲染进去的每一帧的动画,所以它就能造成一个互动的状态。
四、Cocos 的音频播放及革新
最初,讲一下 Cocos 音视频的播放及革新。
Cocos 的音视频播放相对来说是比较简单的,IOS 是 OpenAL,Android 是 OpenSL,Web 是 WebAudio 和 DomAudio,也是分不同的平台去做的。
这是 Cocos 引擎的音频。其实在引擎当中比较简单,一个是循环播放的相似于背景音乐,还有一个是音效,比如说我发一个子弹的音效的声音。
在这边,咱们还是基于下面的例子,也是对音频在挪动端进行了轻微的革新,次要是为了替换 ffplay 程序中的 SDL 音频相干接口,次要是开启、敞开、暂停和复原等。
接下来,咱们也会在音频上退出一些 3D 的音效,反对一些支流媒体的音效平台。方才我讲到的在教育方面的利用,其实咱们在直播上也能够用咱们的 Cocos 引擎去做一些开发方面的互动游戏,今后咱们也会把更多其余场景下的游戏案例分享给大家。
以上是我的分享,谢谢!
对于七牛云、ECUG 和 ECUG Meetup
七牛云:七牛云成立于 2011 年,作为国内出名的云计算及数据服务提供商,七牛云继续在海量文件存储、CDN 内容散发、视频点播、互动直播及大规模异构数据的智能剖析与解决等畛域的核心技术进行深度投入,致力于以数据科技全面驱动数字化将来,赋能各行各业全面进入数据时代。
ECUG:全称为 Effective Cloud User Group(实效云计算用户组),成立于 2007 年的 CN Erlounge II,由许式伟发动,是科技领域不可或缺的高端前沿个人。作为行业技术提高的一扇窗口,ECUG 汇聚泛滥技术人,关注当下热点技术与尖端实际,独特引领行业技术的改革。
ECUG Meetup:ECUG、七牛云联结打造的技术分享系列流动,定位于开发者以及技术从业者的线下团聚,指标是为开发者打造一个高质量的学习与社交平台,期待每一位参会者之间常识的共创、共建和相互影响,产生新知推动认知倒退以及技术提高,通过交换促成行业共同进步,为开发者以及技术从业者打造更好的交流平台与倒退空间。