mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-09-25 01:32:54 +00:00
完善 docs
This commit is contained in:
@@ -63,6 +63,7 @@ TODO
|
||||
- [新特性] cc.Label、cc.RichText、cc.Sprite、cc.MotionStreak、Spine 组件支持使用多纹理材质,并支持自动切换材质机制
|
||||
- [新特性] cc.RichText 支持使用自定义材质
|
||||
- [修复] 直接修改 Effect 的属性不回导致其变体的 hash 值刷新
|
||||
- [修复] CHAR 缓存模式 hash 计算可能会有重复的问题
|
||||
- [调整] 默认禁用 Label 原生 TTF 渲染器
|
||||
|
||||
所有更新日志请移步 [此处](./update-log)。
|
||||
@@ -96,4 +97,9 @@ TODO
|
||||
|
||||
对于已经修改过引擎的人,由于服务包提供的是 Git Patch,所以可以让你在已有修改的基础上轻松应用上服务包的改动,甚至你可以只应用你想要的特性。
|
||||
|
||||
### Cocos Creator 报 Error: Can not parse this input:undefined 错误
|
||||
|
||||
没有找到服务包的内置资源,请记得安装配套的引擎扩展。
|
||||
|
||||
---
|
||||
**最后的最后,希望这个项目能帮助到你的学习或工作,enjoy!**
|
||||
|
@@ -6,3 +6,7 @@ description: "极致地减少游戏 Draw Call。"
|
||||
# 进阶合批指南
|
||||
|
||||
TODO
|
||||
|
||||
动态图集与字符图集使用这个管理器来实现多纹理合批,使用的全局实例可以通过 `cc.sp.multiBatcher` 访问。
|
||||
|
||||
如果你的资源规划地非常细致,项目本身有已经打好的大图集,那么你就可以考虑
|
||||
|
@@ -67,66 +67,66 @@ description: "在游戏开发中享受不用关注 Draw Call 的快乐。"
|
||||
---
|
||||
## 充分利用动态合图
|
||||
|
||||
启用动态合图后,我们有几个小提示能让你发挥出动态合图的潜力:
|
||||
下面几个建议能让你发挥出动态合图的潜力:
|
||||
|
||||
### 放宽能参与合图的纹理尺寸限制
|
||||
|
||||
你可以适当地放宽能参与合图的纹理尺寸的限制(`cc.dynamicAtlasManager.maxFrameSize`)。
|
||||
**动态图集会自动进行多纹理合批,你可以放心地使用多达 8 张图集而不用担心交叉渲染导致的打断批次!**
|
||||
|
||||
推荐设置为 `512`、 `1024` 甚至 `2048`。
|
||||
有了这个新特性,你可以根据项目的具体情况来放宽能参与合图的纹理尺寸限制。
|
||||
|
||||
因为**动态图集会自动进行多纹理合批,你可以放心地使用多达 8 张图集而不用担心交叉渲染导致的打断批次!**
|
||||
```js
|
||||
cc.dynamicAtlasManager.maxFrameSize = 1024; // 推荐 512、1024 甚至 2048
|
||||
```
|
||||
|
||||
:::tip
|
||||
|
||||
服务包会自动将图集最大数量调整至(设备能同时采样纹理数 - Char 缓存模式自动合批图集数),这个值默认为 `7`。
|
||||
服务包会自动将图集的最大数量调整至(设备能同时采样纹理数 - Char 缓存模式自动合批图集数),这个值默认为 `7`。
|
||||
|
||||
:::
|
||||
|
||||
### 无需管理动态图集,只需要释放资源
|
||||
|
||||
**动态合图支持复用废弃空间,释放纹理的同时会释放其在动态图集使用的空间。**
|
||||
**动态合图会在纹理被释放的同时释放其在动态图集使用的空间。**
|
||||
|
||||
所以一般不需要去关心动态图集,只需要做好资源释放,就不会发生动态图集被用完的情况。
|
||||
有了这个新特性,你不需要关心动态图集,只需要做好应有的资源释放,就能保持动态图集的长期有效。
|
||||
|
||||
### 更加细致地优化图集的使用效率
|
||||
|
||||
除了引擎自带的 `packable` 属性可以控制纹理是否会参与动态合图之外。
|
||||
除了通过调整纹理的 `packable` 属性可以控制纹理是否会参与动态合图之外。
|
||||
|
||||
服务包还额外支持了**控制组件是否默认参与动态合图,也可以控制单个组件是否参与动态合图。**
|
||||
**还可以控制组件是否默认参与动态合图,也可以控制单个组件是否参与动态合图。**
|
||||
|
||||
有关动态合图的设置可前往 [动态合图](TODO) 的文档了解详情。
|
||||
可前往 [动态合图](TODO) 的文档了解详情。
|
||||
|
||||
在上面我们推荐可以将纹理尺寸限制放宽到 `2048`,这听起来貌似有点离谱,但只要规划好项目的资源确实可行,比如:
|
||||
在上面我们推荐可以将纹理尺寸限制放宽到 `2048`,这听起来貌似有点离谱,但只要规划得当确实可行,比如:
|
||||
|
||||
- 将优化程度有限但尺寸具大的纹理禁止参与动态合图
|
||||
- 分模块存放资源,将冷门界面(如活动)的纹理禁止参与动态合图,或尽早释放掉
|
||||
- 在资源已经一团糟的项目中,可以直接禁止渲染组件参与动态合图
|
||||
- 禁止优化程度有限但尺寸巨大的纹理参与动态合图
|
||||
- 分模块存放资源,禁止冷门(如活动界面)的纹理参与动态合图或尽早地释放掉
|
||||
- 在资源已经一团糟的项目中,可通过代码禁止某个界面下所有的渲染组件参与动态合图
|
||||
|
||||
完成上面几点这可能需要一些工作量,但能将动态图集用在刀刃上,发挥更大的作用。
|
||||
|
||||
---
|
||||
## Label 不再是合批噩梦
|
||||
|
||||
在项目之前的开发中,我们可能会使用字体图集、调整节点顺序,甚至修改渲染流程来解决 Label 的性能问题。
|
||||
|
||||
但是引擎不是提供了 Bitmap 和 Char 两种缓存模式吗?
|
||||
引擎提供的 Bitmap 和 Char 两种缓存模式在稍大一点的项目上就显得力所不及了:
|
||||
|
||||
是的,但是这两个解决方案与旧的动态合图一样在生产环境中使用太过 "玩具" 了:
|
||||
- Bitmap 缓存模式:字体纹理会打入动态图集,但动态图集却无法复用,随着游戏的进行,图集用完则直接失去作用。
|
||||
|
||||
- Bitmap 缓存模式的缺点:字体纹理会打入动态图集,而动态图集无法复用,随着游戏的进行,图集用完则直接失去作用。
|
||||
- Char 缓存模式的缺点:还是无法复用,并且只有一张图集,图集用完则直接无法渲染,应该没人能接受游戏可能跑着跑着字就全部消失了的情况。
|
||||
|
||||
- Char 缓存模式的缺点:还是无法复用,并且只有一张图集,用完则直接无法渲染,试问谁能接受游戏可能跑着跑着字就全部消失了的情况。
|
||||
|
||||
所以,**服务包几乎重构了 Char 缓存模式,除了解决不能复用的问题之外,由于支持了多纹理渲染,所以既可以与动态图集一起合批,还拥有高达最多 8 张字体图集可以使用!**
|
||||
|
||||
接下来我们有几个小提示能让你知道如何选择合适的缓存模式:
|
||||
但,**服务包重构了 Char 缓存模式,除了解决不能复用的问题之外,由于支持了多纹理渲染,所以既能与动态图集合批,还有最多 8 张字体图集可以使用!**
|
||||
|
||||
### 委以重任一把梭 —— Char
|
||||
|
||||
遇事不决,先选 Char 缓存模式。
|
||||
**如果你不知道该选择什么缓存模式,那就遇事不决,先选 Char 缓存模式。**
|
||||
|
||||
虽然 Char 模式也有一些缺点,但能够应付大多数的场景,由于它既能与动态图集一起合批,还是是按字符进行复用的,所以相比 Bitmap 模式它有着更高的性能优势。
|
||||
虽然 Char 模式也有一些缺点,但由于它既能与动态图集一起合批,还是是按字符进行复用的,所以相比 Bitmap 模式它有着更高的性能优势。
|
||||
|
||||
而且不用担心这 8 张字符图集会被用完,内部会用引用计数自动释放废弃字符所占用的空间,可以试着想一下你的游戏最多在同一帧会显示几个字符。
|
||||
不用担心字符图集会被用完,内部会用引用计数自动释放废弃字符所占用的空间。
|
||||
|
||||
但 Char 缓存模式不适合下面的场景:
|
||||
|
||||
@@ -141,37 +141,37 @@ description: "在游戏开发中享受不用关注 Draw Call 的快乐。"
|
||||
|
||||
在解决了动态图集的复用问题后,Bitmap 缓存模式的纹理也会使用引用计数自动释放,并且不会有 Char 缓存模式无法显示字素簇的问题。
|
||||
|
||||
但当然,Bitmap 缓存模式也不是万能的,如果遇到了下面这种情况就再考虑调整节点顺序等方法来解决吧:
|
||||
但当然,Bitmap 缓存模式也不是万能的,如果遇到了下面这种情况,就需要考虑使用调整节点顺序这样的老办法来解决了:
|
||||
|
||||
- 巨大的字体大小也会瞬间占满整张动态图集
|
||||
- 在非常大量的 Label 需频繁改变文本的情况下,请使用性能分析工具检查动态图集的性能消耗,避免合批的弊大于利。
|
||||
- 巨大的字体大小也会瞬间占满整张动态图集,动态图集也不能这么霍霍。
|
||||
- 在大量的 Label 需频繁改变文本的情况下,请使用性能分析工具检查动态图集的性能消耗,避免合批的弊大于利。
|
||||
|
||||
:::caution 注意
|
||||
|
||||
无论使用哪种缓存模式,在做缩放动画时不要对 `fontSize` 属性进行缓动,这会导致每帧都需要重新生成文字纹理,造成巨大的性能负担,可以使用节点的 `scale` 来代替。
|
||||
|
||||
:::
|
||||
|
||||
### 关于字符图集与动态图集
|
||||
|
||||
常见的误区:
|
||||
**1.Char 缓存模式所使用的字符图集与动态图集并不是一个东西**
|
||||
|
||||
#### 1.Char 缓存模式所使用的字符图集与动态图集是一样的东西,只是叫法不同
|
||||
有多种因素导致没有让 Char 缓存模式直接使用动态图集,在 Char 缓存模式的原理文档中有详细解释。
|
||||
|
||||
由于多种原因,没有设计让 Char 缓存模式直接使用动态图集,这当然可以做到,但是权衡之下选择了分开实现,在使用指南中有详细解释。
|
||||
多纹理材质只有 8 个纹理插槽,所以默认情况下动态图集最大数量为 7,字符图集自动多纹理合批的数量为 1(注意,这个不是指字符图集的最大数量,字符图集的最大数量是 8 张,并且不能调整)。
|
||||
|
||||
多纹理材质只有 8 个纹理插槽,所以默认情况下动态图集最大数量为 7,字符图集自动多纹理合批的数量为 1。(注意不是最大数量)
|
||||
你可以自己调整这个分配值,比如 6 张动态图集,字符图集自动合批 2 张,保持数量加起来不超过 8 张,也就能保持 1 Draw Call。
|
||||
|
||||
你可以自己调整这个分配值,而服务包使用这个默认值有以下几点原因:
|
||||
而服务包使用这个 “7 + 1” 的默认值有以下几点原因:
|
||||
|
||||
- 引擎原本就只有 1 张 Char 字符图集
|
||||
- 大多数项目因为 Char 缓存模式加入了可复用的特性后,1 张 Char 字符图集是足够的
|
||||
|
||||
如果你直觉认为 1 张太少,我们建议你合理搭配使用 Bitmap 和 Char 两种缓存模式后,实际测试发现不够再调整该值。
|
||||
建议你合理搭配使用 Bitmap 和 Char 两种缓存模式后再进行实际测试,发现 Char 字符图集 1 张是真的不够再对其做调整。
|
||||
|
||||
**请注意上面的 1 并非是字符图集的最大数量,而是字符图集进行自动多纹理合批的最大数量!**
|
||||
**2.Char 缓存模式依然不能在图集用完的情况下正常渲染**
|
||||
|
||||
所以这并不意味着字符图集只能有 1 张,而是最大能有 8 张,并且这个数量不能调整。
|
||||
|
||||
如果你还是对为什么会出现一个 “字符图集进行自动多纹理合批的最大数量” 而一头雾水,建议详细阅读使用指南。
|
||||
|
||||
#### 2.Char 缓存模式能在图集满了的情况下依然能正常显示
|
||||
|
||||
现在如果字符图集满了,依旧不能正常显示,这样的原因有以下几点:
|
||||
原因有以下几点:
|
||||
|
||||
- 我们认为 8 张数量已经够多了,8 张都用完的情况大部分是没有合理搭配使用两种缓存模式
|
||||
- 8 张是多纹理渲染的上限,这意味着如果超过 8 张,1 个 Label 有 100 个字,就可能有 100 个 Draw Call
|
||||
@@ -182,7 +182,7 @@ description: "在游戏开发中享受不用关注 Draw Call 的快乐。"
|
||||
以上就是新合批指南的全部内容了,稍微总结一下渲染批次合并的几个要点:
|
||||
|
||||
- 启用动态合图,只需要合理地释放资源即可保持动态合图的一直有效
|
||||
- 能就优先用 Char 缓存模式,不能则换为 Bitmap 缓存模式,字数太多字体太大的则放弃挣扎使用 None 模式
|
||||
- 不要优先考虑打图集,修改节点顺序等需要维护成本的优化方式
|
||||
- 优先使用 Char 缓存模式,不适合则使用 Bitmap 缓存模式,都不适合则采用老方法
|
||||
- 不要优先考虑修改节点顺序这种需要维护成本的优化方式
|
||||
|
||||
如果你对批次合并还有着更高的需求,可以阅读 [进阶合批指南](./advance-batcher-guide)。
|
||||
|
@@ -17,5 +17,6 @@ sidebar_position: 7
|
||||
- [新特性] cc.Label、cc.RichText、cc.Sprite、cc.MotionStreak、Spine 组件支持使用多纹理材质,并支持自动切换材质机制
|
||||
- [新特性] cc.RichText 支持使用自定义材质
|
||||
- [修复] 直接修改 Effect 的属性不回导致其变体的 hash 值刷新
|
||||
- [修复] CHAR 缓存模式 hash 计算可能会有重复的问题
|
||||
- [调整] 默认禁用 Label 原生 TTF 渲染器
|
||||
|
||||
|
BIN
docs/docs/user-guide/multi-render/assets/autoswitch-settings.png
Normal file
BIN
docs/docs/user-guide/multi-render/assets/autoswitch-settings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 85 KiB |
@@ -5,5 +5,121 @@ description: "了解如何手动进行多纹理合批。"
|
||||
|
||||
# 多纹理合批
|
||||
|
||||
在 [新 UI 渲染批次合并指南](../../start-guide/batcher-guide#充分利用动态合图) 中提到了动态合图与多纹理渲染结合后,能让多张图集纹理在同一批次渲染。
|
||||
|
||||
着重介绍管理器。
|
||||
如果你阅读过 [多纹理材质](./multi-material) 文档的话,肯定知道能使用 `MultiHandler` 的接口来动态设置材质的纹理插槽来实现。
|
||||
|
||||
但是这种完全手动的方式实现起来比较麻烦,比如你需要使用一个纹理时,还得找到该纹理所在的材质并设置到渲染组件上。
|
||||
|
||||
为了能更方便地进行多纹理合批,服务包封装了一个自动切换多纹理材质的机制与多纹理合批管理类 `cc.sp.MultiBatcher`。
|
||||
|
||||
动态图集与字符图集使用了一个全局实例,可以通过 `cc.sp.multiBatcher` 访问。
|
||||
|
||||
---
|
||||
## 开关自动切换多纹理材质
|
||||
|
||||
要让动态合图自动进行多纹理合批,首先要解决设置材质的问题,当切换成动态图集的纹理时,需要自动将组件的材质设置为有动态图集纹理的材质。
|
||||
|
||||
所以我们增加了一个机制,在支持的组件内使用开启了该机制的纹理进行渲染时,会提前切换为该纹理关联的材质(只要支持多纹理渲染就支持自动切换材质)。
|
||||
|
||||
这个机制默认是开启的,可以通过全局开关来控制默认值:
|
||||
|
||||
```js
|
||||
cc.sp.autoSwitchMaterial = false;
|
||||
```
|
||||
|
||||
默认情况下组件会使用全局值,你可以控制单个组件是否强制启用/禁用该机制:
|
||||
|
||||

|
||||
|
||||
除了在编辑器调整,也可以通过代码控制:
|
||||
|
||||
```js
|
||||
// cc.RenderComponent.EnableType
|
||||
// GLOBAL: 全局默认值
|
||||
// ENABLE: 开启
|
||||
// DISABLE: 关闭
|
||||
sprite.autoSwitchMaterial = cc.RenderComponent.EnableType.ENABLE;
|
||||
```
|
||||
|
||||
:::caution 注意
|
||||
|
||||
组件有脏检查标记,如果修改全局开关或者修改纹理关联的材质,需要对所有使用该纹理的渲染组件调用 `comp.setVertsDirty()` 重新检查。
|
||||
|
||||
:::
|
||||
|
||||
:::caution 特别注意
|
||||
|
||||
如果 Spine 组件所使用的 `SkeletonData` 同时使用了多个纹理,那么只会遍历数据以找到的第一个纹理为主执行自动切换机制。
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
## 设置纹理的关联材质
|
||||
|
||||
:::info
|
||||
|
||||
每个纹理只能关联一个材质,如果同一个纹理,不同的渲染组件需要使用不同材质就需要手动设置。
|
||||
|
||||
:::
|
||||
|
||||
关联材质的接口有两种用法:
|
||||
|
||||
```js
|
||||
const bool = texture.linkMaterial(material);
|
||||
const bool = texture.linkMaterial(material, index);
|
||||
```
|
||||
|
||||
第一句代码会自动将纹理设置到材质的空插槽中,然后将该材质设置为该纹理的关联材质,如果没有空插槽会返回 `false`。
|
||||
|
||||
第二句则是强制将纹理设置到指定的插槽中,并将该材质设置为该纹理的关联材质。
|
||||
|
||||
想要解除两者的关联可以使用:
|
||||
|
||||
```js
|
||||
texture.unlinkMaterial();
|
||||
```
|
||||
|
||||
获取关联的材质可以使用:
|
||||
|
||||
```js
|
||||
const material = texture.getLinkedMaterial();
|
||||
```
|
||||
|
||||
---
|
||||
## 多纹理合批管理器
|
||||
|
||||
手动关联材质就意味着你需要手动创建并管理创建的所有材质,如果是大量纹理需要关联材质就会比较麻烦。
|
||||
|
||||
所以我们封装了一个小巧的多纹理合批管理器 `cc.sp.MultiBatcher`。
|
||||
|
||||
这个管理器有点像动态合图管理器,它会持有一个材质数组,初始化后会使用内置的多纹理 Effect 着色器创建一个材质并放在数组中。
|
||||
|
||||
你可以传给管理器一个纹理,它会查找所有材质的空插槽,如果没有材质有空插槽则会创建一个新材质,然后把纹理与材质关联。
|
||||
|
||||
### 如何使用
|
||||
|
||||
创建管理器并初始化可以使用:
|
||||
|
||||
```js
|
||||
const batcher = new cc.sp.MultiBatcher();
|
||||
batcher.init();
|
||||
```
|
||||
|
||||
传入纹理可以使用:
|
||||
|
||||
```js
|
||||
const material = batcher.requsetMaterial(texture);
|
||||
```
|
||||
|
||||
会返回关联的材质,如果纹理本来就已经有关联的材质,则会直接返回已关联的材质。
|
||||
|
||||
清空内部数组可以使用:
|
||||
|
||||
```js
|
||||
batcher.reset();
|
||||
```
|
||||
|
||||
### 它的用途
|
||||
|
||||
在 [进阶合批指南](../../start-guide/advance-batcher-guide) 中有提供一些常见的使用案例。
|
||||
|
@@ -6,6 +6,7 @@ toc_max_heading_level: 5
|
||||
|
||||
# 多纹理材质
|
||||
|
||||
---
|
||||
## 创建多纹理材质
|
||||
|
||||
你可以正常创建一个材质文件,Effect 选择内置的多纹理 Effect 着色器 `multi-2d-sprite` 即可。
|
||||
@@ -14,6 +15,7 @@ toc_max_heading_level: 5
|
||||
|
||||
勾选 `USE_MULTI_TEXTURE` 后可以看到上面有 `texture` - `texture8` 一共 8 个纹理插槽,将需要使用的纹理拖到上面的插槽即可完成多纹理材质的配置。
|
||||
|
||||
---
|
||||
## 在组件中使用多纹理材质
|
||||
|
||||
直接拖到组件的 `Materials` 属性上即可。
|
||||
@@ -36,6 +38,7 @@ toc_max_heading_level: 5
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
## 自定义多纹理材质
|
||||
|
||||
上面介绍的多纹理材质都是使用的内置的多纹理 Effect 着色器,你可以直接在内置多纹理 Effect 着色器的基础上修改。
|
||||
@@ -56,6 +59,7 @@ toc_max_heading_level: 5
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
## 通过代码设置纹理插槽
|
||||
|
||||
每个多纹理材质都对应着一个多纹理材质管理器,这是服务包新增的一个工具类,其主要用处是便捷、高性能地管理多纹理材质上面的纹理插槽。
|
||||
@@ -76,6 +80,9 @@ handler.setTexture(1, null);
|
||||
|
||||
// 直接移除指定纹理
|
||||
handler.removeTexture(texture.getImpl());
|
||||
|
||||
// 将纹理自动设置到材质的空插槽
|
||||
handler.autoSetTexture(texture);
|
||||
```
|
||||
|
||||
从上面的代码中可以看出操作纹理插槽的时候并不是传入插槽的名称,而是需要提供下标。
|
||||
@@ -100,12 +107,13 @@ cc.sp.propertyName2Index("texture"); // return: 0
|
||||
|
||||
:::caution 警告
|
||||
|
||||
请勿直接通过 `setProperty` 接口修改多纹理材质的纹理插槽。
|
||||
请勿直接通过材质原始的 `setProperty` 接口修改多纹理材质的纹理插槽。
|
||||
|
||||
如果你必须这么做,需要调用 `material.getMultiHandler().syncTextures()` 来同步插槽数据到 `MultiHandler` 上。
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
## 强制设置材质的类型
|
||||
|
||||
如果你想将某个材质强制视为多纹理材质或非多纹理材质,可以:
|
||||
@@ -118,4 +126,4 @@ material.setMultiSupport(true);
|
||||
material.setMultiSupport(false);
|
||||
```
|
||||
|
||||
但是这么做好像没有什么意义。
|
||||
没有特殊情况不需要这么做。
|
||||
|
Reference in New Issue
Block a user