描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个物体。下面使用Shader实现简单的描边效果。
描边的实现通常有两种方式:一种是将模型顶点沿法线方向扩展一段距离,一种是使用深度偏移。
一、通过法线的延伸
原理:进行两次渲染,第一次剔除正面只渲染背面,把模型顶点沿法线方向延伸一定距离,只显示描边的颜色
第二次渲染剔除背面,只显示正面正常渲染。
Shader "Custom/Stroke"
{
Properties
{
_MainTex("main tex",2D) = ""{}
_Factor("factor",Range(0,0.1)) = 0.01 //描边粗细因子
_OutLineColor("outline color",Color) = (0,0,0,1)//描边颜色
}
SubShader
{
Pass
{
Cull Front //剔除前面
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 vertex :POSITION;
};
float _Factor;
half4 _OutLineColor;
v2f vert(appdata_full v)
{
v2f o;
//将顶点沿法线方向向外扩展一下
v.vertex.xyz += v.normal * _Factor;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
half4 frag(v2f v) :COLOR
{
//只显示描边的颜色
return _OutLineColor;
}
ENDCG
}
Pass
{
Cull Back //剔除后面
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 vertex :POSITION;
float4 uv:TEXCOORD0;
};
sampler2D _MainTex;
v2f vert(appdata_full v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
return o;
}
half4 frag(v2f v) :COLOR
{
half4 c = tex2D(_MainTex,v.uv);
return c;
}
ENDCG
}
}
FallBack "Diffuse"
}
二、深度偏移
原理:进行两次渲染,第一次剔除正面只渲染背面,利用Offset指令,进行深度操作。
第二次渲染剔除背面,只显示正面正常渲染。
Offset 深度偏移
Offset Factor , Units
Factor : 主要影响我们绘制多边形的深度斜率的最大值
Units : 主要影响的能产生的在窗口坐标系的深度值中可变分辨率差异的最小值。
一般在使用Offset指令中,Units给一个统一值就行,主要起作用的是Factor.,Factor的调整是沿着Z轴方向的,Factor大于0,偏移值就沿着Z轴正方向移动,离屏幕越远。Factor小于0,偏移值就沿着Z轴的负方向,离屏幕近。
Shader "Custom/Stroke2" {
Properties
{
_MainTex("main tex",2D) = ""{}
_OutLineColor("outline color",Color) = (0,0,0,1) //描边颜色
}
/*
Offset:深度偏移
Offset Factor,Units
Factor参数表示 Z缩放的最大斜率的值。
Units参数表示可分辨的最小深度缓冲区的值。
*/
SubShader{
//描边
pass {
Cull Front //剔除正面
Offset -5,-1 //深度偏移
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
half4 _OutLineColor;
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata_base v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
float4 frag(v2f i) : COLOR{
return _OutLineColor;
}
ENDCG
}
//正常渲染物体
pass {
Cull Back //剔除背面
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
float4 frag(v2f i) : COLOR
{
float4 c = tex2D(_MainTex,i.uv);
return c;
}
ENDCG
}
}
FallBack "Diffuse"
}
效果图: