关于Unity在2D的UGUI和3D模型交错时渲染顺序的一点探讨
来源:互联网 发布:万德数据 编辑:程序博客网 时间:2024/05/18 13:25
0.前言
写下此文,主要是因为近来学习了一点UGUI的知识,便想着做个小玩意儿作为“毕设”,想做的内容很简单,就是实现在按钮上插入一个3D模型(最近很火的手游《王者荣耀》上就有类似的设计),没想到在渲染顺序的问题上栽了跟斗,一番搜索过后,发现居然打开了新世界的大门。文末附有本文实验用的工程。
1.Unity如何控制渲染顺序
综合文章[1]和[2],笔者认为影响渲染顺序的因素有一下四个:Camera Depth,Sorting Layer,Order In Layer,RenderQueue。关于这四个因素的排序规则,文章[1]给出了以下结论:
1、Camera Depth永远最高。Camera Depth小的一定先进渲染管线。 2、当Sorting Layer和Order In
Layer相同时,RenderQueue小的先进渲染管线。 3、当Sorting Layer和Order In Layer不相同时:
3.1 当两个材质使用了不同的RenderQueue,且这两个RenderQueue都在[0~2500]或[2501~5000]时,SortingLayer和OrderInLayer的排序生效。
3.2 当两个材质使用了不同的RenderQueue,且这两个RenderQueue分别在[0~2500]和[2501~5000]时,则一定会按照RenderQueue绘制,无视SortingLayer、OrderInLayer的排序。
4、MehRenderer的sortingLayer与Canvas的sortingLayer同级;MehRenderer的sortingOrder与Canvas的OrderInLayer同级
以上结论,笔者经过实验(工程中/Assets/TestOrder/TestOrder1场景),于文[1]是一致的,这里文[1]的解释是2500是非透明物体与透明物体渲染队列的分界点(关于RenderQueue可以参考[3]),所以当渲染的sprite同为非透明物体或者同为透明物体时,是根据其SortingLayer、OrderInLayer来排序。
然而,此结论对于UGUI而言,又有所不同。对于UGUI,属于同一个Canvas的控件,其SortingLayer、OrderInLayer都是相同的。根据上面的结论,RenderQueue应该是可以控制控件的渲染顺序,但笔者实验发现(工程中/Assets/TestOrder/TestOrder2场景),通过给控件挂上自定义的material并改变其RenderQueue并不能调整控件的层级关系,真正决定控件渲染顺序的只有控件与其兄弟节点在parent中的相对顺序如图1所示。
Front
BG
图1 UGUI同一个Canvas下改变控件的RenderQueue
Front的RenderQueue是2504,BG的RenderQueue是2603,然而Front还是在前面。结论:对于UGUI上的控件(如image),其Material的RenderQueue并没有什么用,排序规则仍然是与其它使用UGUI默认material的控件按照节点顺序排序
2.如何在一个UGUI的控件中插入一个3D模型
在2D的UI里面插入一个3D模型的做法有很多种,笔者见过的一个做法是,先将控件的Rect转换到Screen Space,然后将其在Screen Space中所占的比例(如图2)传给3D模型的PS,在PS中利用四个边界做culling。
鉴于此种做法需要一些让人头疼的计算,笔者决定偷懒,借助Stencil Buffer来实现,大致的思路是先在Stencil Buffer上把3D模型要展示的区域标记出来,然后再画3D模型,没有标记的区域就不绘制,这样就可以保证挂在某个控件上的模型不会穿到其它控件上面去。
最终的效果如图3所示,图中用一个Cube加一个Sphere作为模型的实例,按钮是蓝色区域,可以看到蓝色区域外是不会显示模型的。具体的实现包含在工程中(工程中/Assets/ ModelOnButton / ModelOnButton场景)。
图3模型负载UGUI的按钮上
此处有坑点,上面说到,要保证模型顺利绘制,我们需要先在待绘制区域用Stencil Buffer标记,那么要保证先标记,就需要保证可以先在该区域先渲染一些东西,可以是mesh,但最好是一个UGUI的控件(如image),因为这样可以利用UGUI上一些布局控制,做到与Button的区域完全匹配,而不用在3D控件中把一个mesh对齐到一个2D控件(可以规避一系列烦人的数学运算)。
笔者的第一版是简单的修改了在Stencil Buffer上坐标的shader的RenderQueue,使其小于模型shader的RenderQueue,这在默认情况下(Canvas的SortingOrder=0)是可以正常运作的,但是当Canvas的SortingOrder>0时,模型就看不到了。几番探索,最终通过在3D模型上挂一个Script,用来将模型下所有Renderer的SortingOrder都改为比Canvas大1解决了此问题。此处与文[1]中结论的冲突在于,UGUI的默认shader应该是Transparent(3000),而此处笔者用于绘制3D模型的shader是Geometry(2000),根据文[1],3D模型应该先绘制,而实际上是UI先绘制了(不然模型不可能显示),而文[3]中也有说明Geometry会先于Transparent。关于这个问题,笔者至今不解,unity关于这方面的资料不是很充分,查起来十分费劲。好在此次的“毕设”算是完成了,可以先告一段落,后续若有新的发现再作补充,另外,也希望知道此问题答案的大神不吝赐教,感激不尽。
参考文献:
[1] http://blog.csdn.net/u011748727/article/details/68947207
[2] http://www.cnblogs.com/LeonLazuli/p/3961283.html
[3] http://blog.csdn.net/candycat1992/article/details/37345251
- 关于Unity在2D的UGUI和3D模型交错时渲染顺序的一点探讨
- Unity3D中UGUI及3D模型渲染的DrawCall优化
- 关于3D环境的建立和渲染代码
- Unity中2D和UGUI图集的理解与使用
- XNA:2D图元与3D模型共存时的渲染问题
- XNA:2D图元与3D模型共存时的渲染问题
- XNA:2D图元与3D模型共存时的渲染问题
- [Unity官方文档翻译]2D or 3D Projects Unity中2D和3D项目的区别
- 关于UGUI挡道3D的物体触发点击事件无法和3D物体分离的解决方案
- unity学习日记:怎样在UI界面上渲染3D模型
- 3D物体在UGUI下的坐标映射
- 【Unity 3D学习】把3D模型放置到2D平面的两种方法
- Unity 3D 海水的实现2 折射与反射 离屏相机的渲染
- 关于3D模型的搜索算法
- 关于printf("%d,%d",num++,++num); 打印结果的探讨
- Hello World 3D, 简单的3D 渲染 + MD2 模型
- UNity UGUI 2D图片追随问题
- UGUI Image的2d碰撞检测
- Linux学习------目录架构
- bzoj1850: Submatrix
- leetcode解题报告22. Generate Parentheses
- POJ 3422 Kaka's Martix Travels 费用流模板
- php 实现信息采集(网页内容抓取)程序代码
- 关于Unity在2D的UGUI和3D模型交错时渲染顺序的一点探讨
- 资源
- 【POJ3009】Curling 2.0(深搜)
- 最小生成树Prim算法理解
- JZOJ 3766. 【BJOI2014】大融合
- 当国家选择是香港时运输方式:EUB、EUB2、SHEUB 中的邮编栏置灰
- bitset位集合容器
- aizu/aoj-0118-Property Distribution
- AES加密算法(加密字符串):Rijndael