赞
踩
https://www.jianshu.com/p/0341f0ab9020
在Unity Shader中会经常在SubShader中使用Tags,其中就会涉及RenderType和Queue,如:
SubShader{
Tags{"RenderType"="Opaque" "Queue"="Geometry"}
...
}
RenderType
RenderType通常使用的值包括:
Opaque: 用于大多数着色器(法线着色器、自发光着色器、反射着色器以及地形的着色器)。
Transparent:用于半透明着色器(透明着色器、粒子着色器、字体着色器、地形额外通道的着色器)。
TransparentCutout: 蒙皮透明着色器(Transparent Cutout,两个通道的植被着色器)。
Background: Skybox shaders. 天空盒着色器。
Overlay: GUITexture, Halo, Flare shaders. 光晕着色器、闪光着色器。
TreeOpaque: terrain engine tree bark. 地形引擎中的树皮。
TreeTransparentCutout: terrain engine tree leaves. 地形引擎中的树叶。
TreeBillboard: terrain engine billboarded trees. 地形引擎中的广告牌树。
Grass: terrain engine grass. 地形引擎中的草。
GrassBillboard: terrain engine billboarded grass. 地形引擎何中的广告牌草。
这些RenderType的类型名称实际上是一种约定,用来区别这个Shader要渲染的对象,当然你也可以改成自定义的名称,只不过需要自己区别场景中不同渲染对象使用的Shader的RenderType的类型名称不同,也就是说RenderType类型名称使用自定义的名称并不会对该Shader的使用和着色效果产生影响。
指定RenderType的名称,主要是为了配合使用替代渲染的方法:
Camera.SetReplacementShader("shader","RenderType")
在使用替代渲染方法时,相机会使用指定的 shader 来代替场景中的其他 shader 对场景进行渲染。比如现在有 shader1:
Shader "shader1"{
Properties{...}
SubShader{
Tags{"RenderType"="Opaque"}
Pass{...}
}
SubShader{
Tags{"RenderType"="Transparent"}
Pass{...}
}
}
场景中一部分物体当前使用的是 shader2:
Shader "shader2"{
Properties{...}
SubShader{
Tags{"RenderType"="Opaque"}
Pass{...}
}
}
另一部分使用的是 shader3:
Shader "shader3"{
Properties{...}
SubShader{
Tags{"RenderType"="Transparent"}
Pass{...}
}
}
调用替代渲染的方法:
Camera.SetReplacementShader("shader1","")
这种情况下,场景中所有的物体就都使用shader1进行渲染(当Shader中包含多个SubShader,在渲染时显卡根据性能从上到下选择第一个能支持的shader)
如果在调用时,第二个参数不为空字符串,即:
Camera.SetReplacementShader("shader1","RenderType")
这种情况下,首先在场景中找到标签中包含该字符串(这里为"RenderType")的shader,再去看标签中的该字符串的值与shader1中包含该字符串的值是否一致,一致的话,替换渲染,否则不渲染;由于shader2中包含"RenderType"="Opaque",而且shader1中的第一个SubShader中包含"RenderType"="Opaque",因此将shader1中的第一个SubShader替换场景中的所有shader2,同理,将shader1中的第二个SubShader替换场景中的所有的shader3。
如果shader1为:
Shader "shader1"{
Properties{...}
SubShader{
Tags{"RenderType"="Opaque" "A"="On"}
Pass{...}
}
SubShader{
Tags{"RenderType"="Transparent" "A"="Off"}
Pass{...}
}
}
shader2为:
Shader "shader2"{
Properties{...}
SubShader{
Tags{"RenderType"="Opaque" "A"="On"}
Pass{...}
}
}
shader3为:
Shader "shader3"{
Properties{...}
SubShader{
Tags{"RenderType"="Transparent" "A"="On"}
Pass{...}
}
}
替代渲染的调用方式为:
Camera.SetReplacementShader("shader1","A")
最后的结果是,shader1的第一个SubShader将会替换shader2和shader3
Unity中的渲染顺序自上而下大致分为三层。 最高层为Camera层,可以在Camera的depth那里设置,设置之后,图形的渲染顺序就是先绘制depth低的相机下的物体,再绘制depth高的相机下的物体,也就是说,depth高的相机会覆盖depth低的相机(具体的覆盖关系有don't clear, solid color等等几种)
比Camera层稍低一层的是sorting layer层,随便找一个可以设置sorting layer的地方,选择sorting layer,点添加按钮,就可以看到当前所有的sorting layer,并且可以更改sorting layer的顺序,排位靠后的sorting layer会覆盖排位靠前的sorting layer。设置好sorting layer的相互关系之后,就可以给任何一个继承于Renderer类,或者有renderer的子类作为field的对象设置sorting layer了。注意这些sorting layer的遮挡关系是在同一个camera的层级下的。不同camera下的renderer渲染顺序以camera的depth为准。有的component的sorting layer可以直接在unity editor里面设置,比如Sprite Renderer。有的则需要用代码来设置,比如设置Particle system的sorting layer,就需要在代码中取到 ParticleSystem.Renderer.SortingLayer 来进行设置。
比sorting layer再低一层的是sorting order,这个数字指代的是在同一个sorting layer下的渲染顺序,用法很明显就不赘述了。
需要注意不要混淆的是gameobject的layer,和renderer的sorting layer。 gameObject的layer个人理解是一个逻辑上的分层,用于camera的culling mask等。而renderer的sorting layer则用于渲染。只有继承与renderer或者有renderer作为filed的component才需要设置sorting layer。
另外需要指出的是,常用的NGUI的widget depth其本质也是一个sorting layer下的sorting order。 NGUI好像用的是一个叫做“UI"的sorting layer。由此大家如果有需要,也可以自己取Hack NGUI的代码,把NGUI的sorting layer暴露出来供自己定制。
简单总结一下,决定Unity渲染关系的层级顺序是:
Camera
sorting layer
sortingorder
但是这些还不够,因为还没有说到比较让初学者头疼的(笔者一开始就很头疼)RenderQueue ,RenderQueue 其实就是shader中tags中的Queue
Tags { "Queue"="Geometry" }
默认情况下,Unity会基于对象距离摄像机的远近来排序你的对象。因此,当一个对象离摄像机越近,它就会优先绘制在其他更远的对象上面。对于大多数情况这是有效并合适的,但是在一些特殊情况下,你可能想要自己控制对象的绘制顺序。而使用Tags{}块我们就可以得到这样的控制。
Unity提供给我们一些默认的渲染队列,每一个对应一个唯一的值,来指导Unity绘制对象到屏幕上。这些内置的渲染队列被称为Background, Geometry, AlphaTest, GeometryLast,Transparent, Overlay。这些队列不是随便创建的,它们是为了让我们更容易地编写Shader并处理实时渲染的。
同时需在SubShader中显示声明ZWrite Off,通知Unity我们会重写物体的渲染深度排序。
Properties | Value | 渲染队列描述 | 说明 |
---|---|---|---|
Background | 1000 | This render queue is rendered before any others. | 这个队列通常被最先渲染(比如 天空盒)。 |
Geometry | 2000 | Opaque geometry uses this queue. | 这是默认的渲染队列。它被用于绝大多数对象。不透明几何体使用该队列。 |
AlphaTest | 2450 | Alpha tested geometry uses this queue. | 需要开启透明度测试的物体。Unity5以后从Geometry队列中拆出来,因为在所有不透明物体渲染完之后再渲染会比较高效。 |
GeometryLast | 2500 | Last render queue that is considered “opaque”. | 所有Geometry和AlphaTest队列的物体渲染完后 |
Transparent | 3000 | This render queue is rendered after Geometry and AlphaTest, in back-to-front order. | 所有Geometry和AlphaTest队列的物体渲染完后,再按照从后往前的顺序进行渲染,任何使用了透明度混合的物体都应该使用该队列(例如玻璃和粒子效果) |
Overlay | 4000 | This render queue is meant for overlay effects. | 该队列用于实现一些叠加效果,适合最后渲染的物体(如镜头光晕)。 |
好了,最后给出一个最终的总结:
依次按条件先后顺序进行排序渲染处理。先按大项条件排序,后按小项条件排序
1.Camera Depth: 越小越优先
2.RenderQueue 2500以下
1. Sorting Layer/Order in Layer
1. 按照Sorting Layer/Order in Layer 设置的值,越小越优先
2. 无此属性,等同于 Sorting Layer=default ,Order in Layer=0 参与排序
2.RenderQueue 越小越优先
3.RenderQueue 相等,由近到远排序优先
3.RenderQueue 2500以上
1. Sorting Layer/Order in Layer
1. 按照Sorting Layer/Order in Layer 设置的值,越小越优先
2. 无此属性,等同于 Sorting Layer=default ,Order in Layer=0 参与排序
2.RenderQueue 越小越优先
3.RenderQueue 相等,由远到近排序优先
说明一下:2500是关键值,它是透明跟不透明的分界点,因此我们考虑层级的时候要注意着点:renderqueue > 2500的物体绝对会在renderqueue <= 2500的物体前面,即渲染时renderqueue大的会挡住renderqueue小的,不论它的sortingLayer和sortingOrder怎么设置都是不起作用的。知道了这点,其他的就很好理解了。当两个的RenderQueue都在同一侧时,在SortingLayer高的绝对会在sortingLayer前面,无视renderqueue跟soringOrder,只有在sortingLayer相同的前提下,soringOrder高的会在sortingOrder低的前面,无视renderqueue。当sortingLayer跟sortingOrder相同时,才看renderqueue的高低,高的在前面。
UGUI中的ui默认使用的是UI/Default 材质,对应的shader中的渲染队列是Transparent
- Shader "UI/Default"
- {
- Properties
- {
- ...
- }
-
- SubShader
- {
- Tags
- {
- "Queue"="Transparent"
- "IgnoreProjector"="True"
- "RenderType"="Transparent"
- "PreviewType"="Plane"
- "CanUseSpriteAtlas"="True"
- }
- ...
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。