描边是个常用的,之前也写过一些,有很多方式。
1.比较简单的一种是两个shader,第一个正常渲染,另外一个做顶点外扩,设置ztest在正常的pass之后,或者深度也做偏移。
Shader "Custom/Outline"
{
Properties
{
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
_OutlineThickness ("Outline Thickness", Range (0.0, 0.03)) = 0.01
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
Name "OUTLINE"
Tags { "LightMode" = "Always" }
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float4 color : COLOR;
};
float _OutlineThickness;
float4 _OutlineColor;
v2f vert (appdata v)
{
// 对顶点进行法线方向扩展
v2f o;
float3 norm = mul((float3x3)unity_ObjectToWorld, v.normal);
o.pos = UnityObjectToClipPos(v.vertex + float4(norm * _OutlineThickness, 0));
o.color = _OutlineColor;
return o;
}
float4 frag (v2f i) : SV_Target
{
return i.color;
}
ENDCG
}
}
FallBack "Diffuse"
}
2.另外一种是做边缘光,控制范围和颜色。原理就是根据视角和顶点法线的夹角判断边缘,控制阈值,在边缘部分变色。这样的问题是模型描边不只是外轮廓,模型比较陡峭的边缘效果很奇怪,有可能不能正常出现描边。
3.还有一种是基于屏幕后处理的方式。这种如果是要只给模型做描边,需要类似urp的管线修改,或者用多相机。
Shader "Custom/SobelOutline"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata_t
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata_t v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
float4 frag (v2f i) : SV_Target
{
// Sobel滤波器代码(省略)
return tex2D(_MainTex, i.uv);
}
ENDCG
}
}
FallBack "Diffuse"
}
先记录思路,后面补shader。。。