最近在继续研究 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主要是为了演示用,所以不讲究编码优雅与否,性能如何,只是为了配合演示。





















































