最近在继续研究 LoS - 视野, 光照, 阴影 实现分享 相关技术内容的时候,涉及到了大量需要使用 FBO
的地方,比如 gpu 实现 阴影的计算和渲染。
论坛中搜了下,只有大量的问题贴和少量的例子贴。参考了一些帖子和官方例子,虽然能简单实现功能,但是这东西用起来真的问题挺多。
于是就花了一些时间,把这个功能好好的整理,设计,扩展了一下,做了比较方便易用的插件。
注意插件是收费的 (给大哥挣点华子钱),看过下面的文章,如果你感兴趣的话可以考虑购买支持一下 ^_^/
PS: 插件已经通过审核,下载地址戳这里
0x01 About && 关于
RenderTexture
简称 RTT
,指的是使用 FBO -- Frame Buffer Object
技术来实现实时的纹理渲染。
在 multi-pass
的时候经常要使用 RTT
技术,包括一些 post-effect
后期。
0x02 Scenarios && 使用场景
上面简单提到了 FBO
的应用场景,下面就来细分一下这些例子,其中大部分的使用场景,都是和 Shader
相关的。
Multi-Pass Shader
大部分 Shader
效果只需要干一次活,就可以实现效果,比如说一个 GrayScale Shader
,或者 Outline Shader
。
但是有些效果,干一次活不够,而且这些活又不能合并到一次做完。
一个例子,就是模糊效果,模糊效果有很多实现方式可以一次搞定,比如高斯模糊,径向模糊,均值模糊。
但是也有需要多次渲染才能实现的效果,比如说先进行水平模糊,再对第一次渲染输出的纹理,进行垂直模糊,达到最终效果。
对应 Creator
中的实际操作,可以将第一次 Shader
处理 cc.Node
后的纹理结果,渲染到 RenderTexture
对象,然后再将第二次 Shader
作用于 RenderTexture
对象,这样最后的输出纹理,就是想要的结果。
Screen Post-Effect Shader
屏幕后期特效,很多游戏中,都很常见,比如射击游戏中,血量低下时屏幕四周的血液效果,人物跑动后体力不足,屏幕边缘的模糊,或是呼吸效果。
要实现这些效果都可以使用 Shader
但是这些 Shader
的作用对象,应该是整个屏幕纹理渲染到的 RenderTexture
中的纹理。
UV-Related Shader
Creator
中的很多 Shader
在实际使用时会生奇怪的错误,论坛上经常提到,最常见的一个原因,就是勾选了纹理打包选项, Shader
中使用的纹理坐标错误,从而导致最终 Shader
效果的错误。
很多 Shader
完全不关心纹理坐标,比如灰度图,黑白效果,等等。
有些 Shader
只关心纹理的相对坐标,比如说一些模糊算法,对于每一个处理的像素,它只关心和它临近的像素的信息。
最后还有一些 Shader
是关注纹理坐标在整个纹理中所处的绝对坐标的,比如一个类似小草摇曳的效果,需要对纹理从上到下赋予幅度递增的弯曲效果。
对于最后一种 Shader
,只要合图就会出现错误,一种解决方案,是对纹理坐标进行简单的换算。
还有一种方法,也可以用 FBO
来解决。就是把目标对象的纹理,渲染到 RenderTexture
,然后将 Shader
作用于 RenderTexture
。
对于帧动画来说,也是属于最后一种情况,每帧切换合图中的不同纹理,如果是纹理绝对坐标依赖的 Shader
,直接使用必然是得不到想要的效果的。
Bones Animation Shader
除了上面提到的三种纹理坐标的情况,还有这一种更特殊的例子,那就是骨骼动画。
比如 Spine
, DragonBones
这些骨骼动画,它们并不只是单纯的在合图中寻找,切换不同的纹理。而是将合图中各种骨骼纹理取出,根据预制好的动画规则,将骨骼纹理进行形变后组合,并且每帧变化,来呈现出动画效果。
对于这样的骨骼动画,和纹理坐标相关的 Shader
在使用时,直接使用,必然会有很多问题,而且也很难像帧动画一样,通过换算纹理坐标来解决问题。
但是同样的,通过使用 FBO
的套路,一样可以解决问题。
Screenshot
一个很常见的使用场景,截图,最后将纹理导出。
Magnifier
另一个很常见的使用场景,就是将 RenderTexture
中的纹理,进行放大或是缩小操作,实现放大镜的效果。
0x03 Component && 组件
既然是这么有用的东西,那么 Creator
中必然有提供。通过使用 cc.Camera
和 cc.RenderTexture
就可以实现 FBO
的效果。但是通过搜索论坛就可以发现,这个东西是个满是坑
的功能。
总有各种各样的问题来阻止使用者实现想要的效果,即使官方已经在测试用例中给出了简单的演示功能。
也正因为如此,有了这次的组件 SSRFBONodeComponent
,就像名字一样,很直接,就是为了能够在 Creator
中方便的使用 FBO
功能而开发的。把各种复杂的易错的细节都在组件中进行了统一处理,使开发者只需要及其简单的设置就可以使用。
目前组件所测试过的,确认支持的 Creator
中的渲染组件:
cc.Sprite
单图精灵
cc.Animation
帧动画
cc.ParticleSystem
粒子系统
cc.Label
文本
cc.RichText
富文本
DragonBones
龙骨骨骼动画
sp.Skeleton
Spine
骨骼动画
以上所有的渲染组件在和 Mask
组件混用是,同样都能够正常使用。
0x04 Mode && 模式
SSRFBONodeComponent
包含了多种模式来满足实际的 FBO
使用需求,主要有如下四种 (截图中红色部分为 FBO
部分,为了方便演示):
SSRFBONodeScreenComponent
全屏 FBO
专用组件,用于获取全屏纹理。可以用于实现如全屏模糊的效果。
SSRFBONodeRegionComponent
指定大小区域 FBO
专用组件,用于获取节点问中心的,指定大小区域的纹理。可以用于实现如局部区域模糊的效果。
SSRFBONodeInPlaceComponent
指定区域 FBO
专用组件,用于获取指定区域范围内的纹理。可以用于实现如局部区域倒影的效果。
SSRFBONodeTargetComponent
指定对象 FBO
专用组件,用于获取指定对象的纹理。可以用于实现一些骨骼动画相关的 Shader
效果。
0x05 Features && 功能
Common
UpdateMode
更新模式,可以根据需要求,选择是进更新一次纹理,还是实时更新。
根据实际的使用场景,选择合适的更新模式,可以提升 FBO
的性能。比如用户可以在选择 UpdateOnce
模式,然后再需要更新纹理的时候,主动调用 UpdateFBO
接口即可。
flipY
可以指定纹理是否需要翻转。
最常使用 cc.SpriteFrame
的 flipY
属性来实现,但是该属性配合 cc.RenderTexture
使用的时候,在动态运行时更新后无法马上刷新纹理。因此暂时改用 -scaleY
实现。
group
指定 FBO
相关节点专用的分组。
backgroundColor
可以指定 FBO
对象的背景颜色。
RegionComponent
zoom
可以指定纹理的缩放比例,实现类似放大镜的效果。
InPlaceComponent
rect
指定抓取纹理的矩形范围。
编辑器中,有 gizmo
会标识出实际抓取的纹理矩形范围。
TargetComponent
target
指定抓取纹理的对象节点。
syncAngle
syncScale
syncSize
syncAnchor
可指定是否需要和对象的旋转 / 缩放 / 尺寸/锚点 属性保持同步。
在需要精准的纹理计算时,可以开启,这样就会保证 FBONode
和目标节点的 BoundingBox
保持同步。
**目前发现,Creator
中的 RenderTexture 在原生环境下调用 UpdateSize
存在 bug
,暂时采用重新创建纹理的方式实现,因此 syncSize
的性能降低。 **
offsetX
offsetY
可指定抓取后的纹理的横向 / 纵向偏移量。
对于某些骨骼动画,通过设置该属性,可以将渲染目标节点调整到合适的位置。
inflateW
inflateH
可指定输出纹理在宽度 / 高度上的膨胀大小。主要用于一些需要外扩的 Shader
情况。
在测试中发现 Creator
中目前对有些 Spine
动画在大小读取上有问题,比如官方例子中的 SpineBoy
,添加到编辑器中后,size
的大小显示为 0, 0
。但是 SpineRator
则是正确的。
对于前一种情况,可以通过设置 inflate
属性,来实现正确的纹理抓取。
CaptureComponent
接受一个 FBOComponent
对象,并将其中的纹理导出为图片。目前实现了 Web
android
iOS
平台中的导出图片功能。
Editor
所有的控件几属性均可以在编辑器中实时预览,所见即所得。
0x06 Platform Support && 平台支持
目前测试过的平台,设备,相关信息。
从测试结果来看,所有功能在所有测试的平台和设备上都可以正常运行 (除了微信小游戏没有做保存图片的功能)。
引擎版本
Creator v2.3.4
Creator v2.4.0
Creator v2.4.3
测试设备
Model.1
2018 产
MacBook Pro (13-inch)
macOS Catalina 10.15.6
Google Chrome 版本 85.0.4183.83(正式版本)(64 位)
Firefox 80.0.1 (64 位)
Safari 版本13.1.2 (15609.3.5.1.3)
Model.2
2014 产
iPhone 6 11.3.1 MG4H27P/A
Model.3
2017 产
iPhone X 13.3.1 MQA92CH/A
Model.4
2017 产
Huawei Honor 7X BND-AL10 Android 9.0 EMUI 9.1.0
Model.5
2018 产
Huawei Mate20 Pro LYA-AL00 Android 10.1 EMUI v10.1.0
发布平台 / 测试结果
Web Desktop
所有测试用例在 Model.1
所有浏览器中都可以满帧运行。
Web Mobile
所有测试用例在
Model.3/4/5/6
微信浏览器和系统默认浏览器中都可以满帧运行。
Model.2
系统默认浏览器中,部分测试用例为 30 ~ 40FPS
,其余都可以满帧运行。
Mac
Xode Version 11.6 (11E708)
所有测试用例在 Model.1
中都可以满帧运行。
iOS
Xode Version 11.6 (11E708)
所有测试用例在
Model.2/3
中,部分测试用例为 30 ~ 40FPS
,其余都可以满帧运行。
Android
Android-29
armeabi-v7a
所有测试用例在 Model.5
中都可以满帧运行。
Model.4
中,部分测试用例为 30 ~ 40FPS
,其余都可以满帧运行。
Wechat Game
稳定版 Stable Build 1.03.2010240
所有测试用例在 Model.2/3/4/5/6
中,部分测试用例为 30 ~ 40FPS
,其余都可以满帧运行。
总结
测试用例性能在各种场景下还是有着很不错的表现。
总体性能 Web
> android
> iOS
。
FBO
在同一场景中数量多会造成性能下降的。
选择合适的组件类型,合适的更新策略,都可以帮助提高性能。
除了 FBOTarget
以外,其他三种类型通常在一个场景中只会用到 1
到 2
个。
0x07 How to use && 使用方法
-
将下载文件夹中的
SSRFBONodeComponent/assets/scripts/ssr
目录,复制到想要使用的项目 -
将下载文件夹中的
SSRFBONodeComponent/packages/ssr-fbo-node
目录,复制到想要使用的项目的packages
目录中 -
在编辑器中,就可以看到
fbo
的插件选项了 -
增加一个给
FBO
专用的分组,名称,顺序都随意。 -
记得在使用
FBO
的插件时,设置group
属性为刚才创建的分组名称 -
FBONodeCaptureComponent
在网页端使用时,需要将SSRFBONodeComponent/assets/scripts/ssr/fbo/download.js
文件导入为插件
0x08 Misc && 杂项
- 下载的项目中,包含了核心的
Component
和源码,和所有的测试用例源码。 - 下载的项目中,组件使用的
Group
名称为fbo
- 测试用例中的
Shader
主要是为了演示用,所以不讲究编码优雅与否,性能如何,只是为了配合演示。