Unity获取透明物体深度数据

时间:2024-04-08 16:16:37

前言

最近在做的项目有很多奇怪的需求,甚至之前在unity里用插件写了一个类似于蓝图的行为树插件,之后有时间给大家讲一讲相关的实现方法,今天刚解决了unity里透明物体无法获得深度数据的问题。所以分享给大家。

透明&景深

景深效果作为一种屏幕后处理技术想必大家都是很了解了,在这里就不做展开了,通过访问相机自带的深度数据就可以很方便的和高斯模糊做插值,模拟大光圈下景深效果。但是因为unity的先天因素,自带的透明shader都不会进行深度检测,而先深度检测后透明处理的两个pass的shader只能渲染出模型内部具有正确深度的图形,而不能让摄像机正确获取到深度信息。本文章旨在解决这种问题。

需求

根据透明的需求一般分为两种,一种是模型的半透明效果,另一种是带透明通道图片/视频中alpha切除效果,我的主要关注的是后者,但是顺便研究了一下前者,我们分别来讨论。

先给大家看一下效果吧:

模型透明度部分

正常不透明物体的深度图
Unity获取透明物体深度数据
使用unity透明shader渲染的物体为半透明,但没有深度图
Unity获取透明物体深度数据
使用我的方法,存在深度图的透明物体
Unity获取透明物体深度数据

带透明通道图片/视频部分

一般的含透明度图片的深度图
Unity获取透明物体深度数据
使用我的方法获取到有深度信息的片面
Unity获取透明物体深度数据

半透明模型获取深度的具体实现方法

思路其实很简单,我觉得大家都想的到,但是不知道为什么我搜了很久没有找到相关的解决方案,所以还是写一下吧,给大家填个坑。
因为透明混合之后unity的摄像机就不能获取该物体的深度图,所以就想办法让模型具有两个材质即可,其中一个负责处理半透明效果,另一个只负责处理和传输模型网格数据,并不需要显示,这样就可以获得深度数据了,是不是很简单:
具体shader:

Properties
	{
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
			};

			struct v2f
			{
				float4 vertex : SV_POSITION;
			};


			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				discard;
				return 0;
			}
			ENDCG
		}
	}
	Fallback "Diffuse"

带透明度图片/视频获取深度的具体实现方法

这个问题困扰了我两天,但是解决办法比想象中的简单很多,之前也是想plane作为一个三维实体应该也可以具有相同的属性,但是用上面的方法尝试之后因为透明度并不会对模型的网格产生变化,所以获取到的深度信息是基于整个plane网格的,于是想有没有什么办法可以剪切掉透明区域的模型网格,于是就在unity的shader资源里发现了一个很优秀的shader,甚至直接使用不用任何操作就可以正常获取深度数据,太窒息了。
shader目录:Unity获取透明物体深度数据
是的就是他,这个被unity雪藏的cutout shader ,救我狗命。

结束语

不管怎样希望帮到大家吧,毕竟是项目里面为数不多的不涉密内容,之后会出一个unity类蓝图插件的编写思路的博客,可惜因为涉密不能谈很多,不过加油吧!