cocos-docs icon indicating copy to clipboard operation
cocos-docs copied to clipboard

渲染排序规则

Open zenskcode opened this issue 3 years ago • 4 comments

URL : https://github.com/cocos-creator/creator-docs/blob/master/zh/ui-system/components/engine/priority.md

某些场景下,Canvas下的父节点不相同的节点也需要根据zorder(深度检测)来调整渲染顺序,即不改变节点顺序的情况下,实现渲染排序,目前的机制无法完成。例如Sprite组件,创建即自动生成Canvas父节点,通过文档介绍的通过自定义材质来开启深度检测,经测试Spirte深度检测无效,删除其父节点Canvas后也无效。

我想了一下引擎可以考虑的思路,对于canvas下的节点, 1.先统一把z为0的节点算好顺序Alist(根据引擎原有的siblingIndex),再把z轴大于0的数值排序Blist, 2.对于z>0的节点,其子节点再依据步骤1操作,直致递归所有的节点。 3.最后先渲染Alist,再渲染Blist。

编辑器上的体现,就是从Y轴(侧面看起来)是可以直接看出前后关系,可以拖动直接调整

其次,期望对于文章中这类可能产生误导的内容予以修正,根据文档的引导,使我认为sprite自定义材质可以实现深度检测,我根据文档下载了官方test-case-3d研究并demo测试,结果发现是无效的,在跟随文档操作的情况下,在一个错误的方向浪费了一些时间。作为开发者,这些损耗的时间是应当承受的。但是作为引擎方,希望能够尽可能避免这类由于文档造成的时间损耗,这也是引擎生态和使用体验的重要组成部分。

预先回答的问题: 1、sprite是2d,确实不需要深度 答:作为引擎用户,这点已经从项目角度论证是需要引擎支持的,这点也已经跟麒麟子同学交流达成一致,我觉得cocos引擎组在需求得到论证的情况下应该多多考虑用户的需求,避免第一反应去否定用户的需求。对比下unity的spriteRender可以实现这一需求,但我不确定是否在canva下,抛开这个对比,上面的需求也希望认真考虑,目前项目因此已经卡壳,计划魔改引擎来实现。

zenskcode avatar Apr 23 '22 08:04 zenskcode

非常抱歉给您带来不好的体验,我下面的回复,可能会让你觉得是在辩解。但是我个人认为还是对我们立场的澄清挺重要的,不论如何我们都希望积极沟通。

先解答一下文档质量问题

目前的文档,传承自早期的 Creator 3D,Creator 3D 又有大量文档是参考 Creator 2.x 写出来的,在 3.0 发布时,我们对 2.x 新版本的文档和 Creator 3D 的文档进行了一次人工合并。由于来源、版本的混乱,确实质量比较差,有些地方都有疏漏。 我们之前专职维护文档的妹子(薰衣),长时间不堪重负,收到研发初稿后,需要自己跑一遍、发现 bug 后要反馈给开发者修复,然后重新截图,(你也知道开发版 bug 肯定很多),还要调整文章逻辑,美化排版,最后翻译成英文…… 所以文档质量一直比较糟糕。 从今年开始,我们将文档工作移交给了成都团队,目前由更加擅长技术的麒麟子领头,不断在进行重写,用更加偏向教程而非参考书的逻辑去优化,力求降低入门门槛的同时修复文档中的错误。

你反馈的文档问题

前面那句话到是强调了深度检测目的是和 3D 物体遮挡,没提到能够修改 UI 顺序。 我个人感觉是这句话导致的误解,麻烦 @UniqueDisplayNameIsInUse 修正一下。

image

你反馈的引擎深度检测问题

1、sprite是2d,确实不需要深度 答:作为引擎用户,这点已经从项目角度论证是需要引擎支持的,这点也已经跟麒麟子同学交流达成一致

我们并不是说 Sprite 不需要排序,而是说 Sprite 无法使用深度排序。

因为透明对象是无法启用深度写入的 GPU depth 的 write 和 test 都是在片元着色器之前进行的,也就是说对 GPU 来说实际上只能以面片为单位实现深度检测。 而 Sprite 实际上是一个矩形(两个三角面),这就导致 Sprite 一旦被遮挡,将会以矩形为单位不进行渲染。哪怕这个 Sprite 是一个全透明的空白 png 图片,也会整个遮挡到后面的其它元素。这在 UI 中几乎是不可能接受的。

所以对 UI 来说,深度检测只会用于非透明对象,例如 UI 和 3D 模型之间进行深度检测。Spirte 和 Spirte 之间没办法使用深度检测。

你反馈的引擎立场问题

搞技术的同学私底下可能会比较直接,让大家感觉容易被忽略,还望大家海涵。其实有这方面抱怨,没多大事,你可以随时找我沟通,相信我的屁股肯定跟麒麟子一样端正。 麻烦 @holycanvas 解答一下 UI 全局排序的实现情况。

jareguo avatar Apr 24 '22 10:04 jareguo

首先,文档确实存在一定误导,目前只有中间件组件(spine, tilemap, dragonbone)填了深度信息,所以也只有这部分能够与 3D 物体混排,这个在文档中没有说明清楚,这部分我们会对文档进行优化

1、sprite是2d,确实不需要深度

sprite 需要深度信息,这个是没什么问题的,引擎这边也不会觉得 2d 就不需要深度的,2d / 3d 混排的需求很常见。我们目前也在将更多的 UI 组件填入深度信息,之前只所以没填,主要是因为目前的 UI 基本是从 2.x 整个迁移过来的,之前 2.x 是没有填深度的(除了切换为 3D 模式),在迁移过来后,当时暂时没考虑到这部分的重构,所以只有中间件这部分填了深度信息。之后我们会为所有的 Ui 组件填上深度信息

关于排序的问题: 首先,目前在 UI 中,引擎选择了使用节点树作为渲染顺序的控制,这个是引擎目前的选择(当然也是基于长期的思考和一一系列的考量),尽管可以想出一些算法,来同时支持全局排序和节点树排序,比如你说的这个方案:

我想了一下引擎可以考虑的思路,对于canvas下的节点, 1.先统一把z为0的节点算好顺序Alist(根据引擎原有的siblingIndex),再把z轴大于0的数值排序Blist, 2.对于z>0的节点,其子节点再依据步骤1操作,直致递归所有的节点。 3.最后先渲染Alist,再渲染Blist。

但是作为通用引擎我们也需要考虑方案的使用者的学习成本,性能表现,方案的可维护性等等众多考量因素。这里的冲突,已经没有办法在算法层以不增加任何复杂度的条件下优雅的解决这个问题了。

当然,我们也完全认同全局排序的重要性,所以针对这个问题,我们分析了用户主要的应用场景认为:

  • UI 方面,大部分 UI 设计师是通过在界面上拖拽来生成 UI 界面,运行时调整渲染顺序需求较少,所以保留以节点树的方式控制渲染顺序
  • 2D 方面,因为 2D 游戏中存在大量节点,且存在运行时调整渲染顺序需求(如玩家被障碍物遮挡),如果没有全局的排序方式,将会非常难以维护,针对这个应用场景,我们将会提供全新的放在 3D 空间下 SpriteRenderer 组件,这个组件不依赖 Canvas,且支持以 Z 值和一个全局排序优先级控制渲染顺序。能够更加方便的与 3D 物体进行混排

我们通过拆分为两个需求,以不同的方式进行支持。这块目前正在实现中,将在 3.6 落地,未来我们也期望大家能将 UI 和 2D 分别使用更方便的方式实现

SantyWang avatar Apr 24 '22 11:04 SantyWang

谢谢二位大大的回复,(这边没有抱怨),提出这些主要是希望引擎组能够收到一些有些价值的声音,我的屁股也坐引擎组这边,期望cocos做得更好!

zenskcode avatar Apr 24 '22 13:04 zenskcode

UI 方面,大部分 UI 设计师是通过在界面上拖拽来生成 UI 界面,运行时调整渲染顺序需求较少,所以保留以节点树的方式控制渲染顺序 2D 方面,因为 2D 游戏中存在大量节点,且存在运行时调整渲染顺序需求(如玩家被障碍物遮挡),如果没有全局的排序方式,将会非常难以维护,针对这个应用场景,我们将会提供全新的放在 3D 空间下 SpriteRenderer 组件,这个组件不依赖 Canvas,且支持以 Z 值和一个全局排序优先级控制渲染顺序。能够更加方便的与 3D 物体进行混排

请问UI下的节点是否计划支持全局Zorder呢?

zenskcode avatar May 01 '22 01:05 zenskcode

@holycanvas SpriteRenderer 组件不支持颜色定制,需要定制材质进行uniform传参,这样会导致合批打断,希望能支持下

LongMarch7 avatar Mar 21 '23 01:03 LongMarch7

建议大家后续的讨论可以提交到引擎仓库,以便有更多实际的推进。https://github.com/cocos/cocos-engine

MrKylinGithub avatar Nov 07 '23 08:11 MrKylinGithub