unity渲染排序

本文介绍了Unity中渲染排序的原理和应用,包括相机深度排序、不透明物体与透明物体的队列处理。通过设置相机的CullingMask和深度,以及物体的渲染模式和渲染队列,可以实现特定的渲染顺序,如确保血条始终显示在模型上方。透明物体之间根据离镜头距离进行渲染,透明与不透明物体的交互可能导致视觉上的交错效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

unity渲染排序

结论

影响渲染排序有这几个
不同相机按深度从小到大排序 > 不透明物体队列在透明物体队列前 > Sorting Layer 从小到大排序 > Order in Layer 从小到大排序 > RenderQueue 从小到大排序 > 深度排序(可能从大到小,也可能从小到大)

相机深度排序

  • 这个是最高级别的,深度低的相机永远先渲染
  • 应用
    模型设为 Layer = Model
    头顶血条设为 Layer = Head
    相机1设置 CullingMask=Model ,深度 -1
    相机2设置 CullingMask=Head,深度0
    则相机2后渲染,血条永远不会被模型盖住

不透明物体队列在透明物体队列前

  • 注意这里是不透明物体队列,不是不透明物体,不透明物体也可以放在透明物体队列,
    只要使用的 shader 采用 “RenderType”=“Opaque”,或材质参数中选择 RenderingMode=Opaque

  • 不透明物体(材质RenderingMode设置为Opaque),渲染时进行深度比较,离镜头近则覆盖,并且修改深度值
    跟其它物体无所谓渲染顺序关系,但所有Opaque物体要最先进行渲染

  • 透明物体之间要排序,按离镜头由远到近进行渲染,渲染时进行深度比较,
    离镜头近则进行混合,但不改变深度值,所有Transparent物体在Opaque渲染后进行渲染
    如果2个Transparent物体有交错,则渲染顺序只跟物体中心点离镜头距离有关系,即使近的物体上的某个点比远的物体
    上的某个点还要远,也会先渲染

  • 由于物体属于哪个队列由 shader 和材质控制,一般只在写 shader 和 材质时考虑,平时的物体排序不考虑该方案

  • 如果存在WorldSpace的Canvas,则把Canvas下的Opaque元素加入到Opaque物体中绘制,
    把整个Canvas做为一个透明物体参与Transparent物体的排序,其z值等于所有UI元素中z值最大值和最小值的平均值,
    然后当绘制Canvas时按照在Hierarchy窗口中的顺序从上到下来绘制UI元素,跟其z值无关

  • 如果 Canvas 要在所有物体最前面,则修改 sortingOrder ,使其在透明物体前,
    修改 shader ,忽略深度检测(ZTest Off 或 ZTest Always 这2句效果一样,默认是 ZTest LEqual),
    使其在不透明物体前,参考 libs/unity/shader/UIOverlay.shader
    如果是修改shader则所有UI元素都得修改显得比较麻烦,有个想法是把 UI 放在最后渲染,然后在 UI 渲染前清除深度值

  • 如果存在Sprite物体,按照普通透明3d物体处理

除了相机深度外的影响排序的变量

主要有 SortingLayer,OrderInLayer,RenderQueue 直接用下面的伪代码解释
	//	影响因素 OrderLayer > OrderInLayer > RenderQueue > SortFlag
	//	下面是推测的排序代码
	var sortFunc = (left,right)=>{
		//	在 SpriteRenderer 组件上设置的 SortingLayer
		//	在 MeshRenderer 组件上要通过代码设置 meshRenderer.sortingLayerName
		if ( left.orderLayer != right.orderLayer )
			return left.orderLayer < right.orderLayer;

		//	在 SpriteRenderer 组件上设置的 OrderInLayer
		//	在 MeshRenderer 组件上要通过代码设置 meshRenderer.sortingOrder
		if ( left.orderInLayer != right.orderInLayer )
			return left.orderInLayer < right.orderInLayer;
		
		//	在 shader 或 材质 中通过 Render Queue 设置
		//	注意 shader 的 RenderType 决定了 Render Queue 的取值范围
		if ( left.RenderQueue != right.RenderQueue )
			return left.RenderQueue < right.RenderQueue;

		//	sortFlag 取决于 shader 中的 RenderType
		//	"RenderType"="Opaque" 不透明物体使用 defaultOpaqueSortFlags
		//	"RenderType"="Transparent" 透明物体使用 CommonTransparent
		if ( sortFlag == SortingCriteria.CommonTransparent )
		{
			//	透明物体按从远到近排序,这样才能正确渲染
			return left.distanceToCamera > right.distanceToCamera;

		}
		else //	( sortFlag == defaultOpaqueSortFlags )
		{
			//	不透明物体从近到远排序,这样提升效率,
			//	因为不透明物体会写入深度,从近到远不影响最终渲染结果
			return left.distanceToCamera < right.distanceToCamera;
		}
	}
  • 我们要测试这几个属性对排序的影响时,应该在透明队列中测试,也就是材质的 RenderingMode=Transparent,
    不透明队列,物体的排序不影响渲染结果,因为会写入深度,且渲染时会对比深度
    透明队列,则物体的排序影响渲染结果,因为只会对比深度,而不会写入深度(不透明物体在透明队列中也一样不写入深度)

应用

  • RenderingMode 和 RenderQueue 是材质和 shader 中用来调整层级,一般写 shader 时才用到
    相机、orderLayer 和 orderInLayer 是用来逻辑上调整层级,是比较常用的
    除了相机,其它变量调整渲染顺序后都会受到不透明物体的深度影响

示例

  • 透明物体和不透明物体的交错
    • 按离相机从近到远有3个物体 A(透明) B(不透明) C(透明)
      显示结果
      B 盖住 C, A 盖住 B
    • 设置 C 的 orderInLayer 为 1,则显示结果
      在 B 的范围内,B 盖住 C, A 盖住 B
      在 B 的范围外,C 盖住 A
      可以看到 A 和 C 会互相穿插,为什么会这样呢
      B 先渲染并写入深度
      A 接着渲染,盖住 B
      C 最后渲染,在 B 的范围内由于 C 的深度比B 大,因此深度测试直接不通过,不渲染
      在 B 的范围外 C 会渲染,盖住 A
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值