unity实现描边的问题汇总

在游戏中,我们都喜欢加一些描边效果,来凸显人物的边缘,提高识别度。美术一般都喜欢加。描边方式一般有两种,一种的模型边缘描边,一种的人物的转折点描边(这种需要用到卷轴)

在游戏中比较常用的就是模型边缘描边了,shader一般是这样

Shader "Outline"
{
	//属性
	Properties{
		_Diffuse("Diffuse", Color) = (1,1,1,1)
		_OutlineCol("OutlineCol", Color) = (1,0,0,1)
		_OutlineFactor("OutlineFactor", Range(0,1)) = 0.1
		_MainTex("Base 2D", 2D) = "white"{}
	}
 
	//子着色器	
	SubShader
	{
		
		//描边使用两个Pass,第一个pass沿法线挤出一点,只输出描边的颜色
		Pass
		{
			//剔除正面,只渲染背面,对于大多数模型适用,不过如果需要背面的,就有问题了
			Cull Front
			
			CGPROGRAM
			#include "UnityCG.cginc"
			fixed4 _OutlineCol;
			float _OutlineFactor;
			
			struct v2f
			{
				float4 pos : SV_POSITION;
			};
			
			v2f vert(appdata_full v)
			{
				v2f o;
				//在vertex阶段,每个顶点按照法线的方向偏移一部分,不过这种会造成近大远小的透视问题
				//v.vertex.xyz += v.normal * _OutlineFactor;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				//将法线方向转换到视空间
				float3 vnormal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);
				//将视空间法线xy坐标转化到投影空间,只有xy需要,z深度不需要了
				float2 offset = TransformViewToProjection(vnormal.xy);
				//在最终投影阶段输出进行偏移操作
				o.pos.xy += offset * _OutlineFactor;
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target
			{
				//这个Pass直接输出描边颜色
				return _OutlineCol;
			}
			
			//使用vert函数和frag函数
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
		
		//正常着色的Pass
		Pass
		{
			...
		}
	}
	//前面的Shader失效的话,使用默认的Diffuse
	FallBack "Diffuse"
}

第一个问题:但是,如果这样放到游戏中回有一定的问题

unity实现描边的问题汇总

可以看到,一些边缘的地方其实没显示边缘色,导致看起来是断层的。

原因是我们剔除了前面unity实现描边的问题汇总,朝向前方的定点被剔除,所以显示不完整。然后我设置为unity实现描边的问题汇总后,unity实现描边的问题汇总

就比较完美了。然后我一位这样就解决了。

第二个问题:但是后面在主场景中发现一个问题unity实现描边的问题汇总可以看到角色整个黑掉了,开始找原因,首先找到的是,人物身体的mesh多了一份,然后把他移除掉一份,其实还是不行。然后因为我们用了两个pass,两个pass都是transparent的,但在frame debug中看渲染顺序也是正常的,说明和渲染顺序无关。

再后来,发现出现这个问题的情景时两个人物叠加在一起。

由于渲染了front,两个英雄的向前的点会重叠(因为渲染完一个人物的两个pass,再到另一个人物的)

然后我想到的解决办法时,加一个模板,但大于等于0的点就设置为Zero。unity实现描边的问题汇总最终解决了这个问题。unity实现描边的问题汇总

可以看到没有显示黑的一团。

第三个问题:在渲染3d和2d结合的界面,如果我们直接渲染3d(而不是用rt来间接实现)的话会出现看不到描边的问题。这个的原因就是因为ui是会在3d模型之后渲染的,然后我们描边是不回写深度的unity实现描边的问题汇总所以会看不到描边(因为由于没写深度,描边在ui后面)。

unity实现描边的问题汇总

因为我们游戏用的是ngui,用uitexture来显示背景,所以会按照ui的方式显示在前面。所以我用了一个quad去实现背景,unity实现描边的问题汇总unity实现描边的问题汇总并且把渲染顺序改为geometry,这样就会显示在后面。unity实现描边的问题汇总

至此就解决了描边的遇到的问题了。

当然很多人可能会说unity实现描边的问题汇总这个挡板也会使描边显示不出来。

对,是会显示不出来,因为他也是ui。但是要根据实际情况并且消耗情况,制作复杂情况来决定。这个挡板没描边是可以接受的,所以我们用一个比较简单消耗低的方式实现。

当然如果你要完全显示描边,那就可以把rt放到camera的target上,然后用uitexture或quad去装载这个rt,就能完全实现,但这样会对一个相机,并且每帧都要去做这样的操作。具体需要自己权衡。