描邊效果的實現方式有很多種,比如後期處理的方式、修改頂點著色器的方式。

本次描邊效果的實現方式就是使用第二種方法。

實現思路大致如下:

實現思路
  1. 第一層,先用一個單獨的pass繪製一個純色的模型,不過要在這個pass裏對頂點著色器做一些特殊處理。
  2. 第二層,繪製正常狀態的效果
  3. 合併兩層為最終效果

下面進入shader講解:

材質屬性

Properties
{
_Albedo ("Albedo", 2D) = "white" {}
_Specular ("Specular Glossiness(RGB A)", 2D) = "black" {}
_Normal ("Normal", 2D) = "bump" {}
_AO ("Ambient Occlusion", 2D) = "white" {}
_Emission("Emission", 2D) = "black"{}

_OutlineColor ("Outline Color", Color) = (1,0,1,1)
_OutlineWidth ("Outline Width", Range(0, 0.1)) = 0.01
}

定義了Unity Specular標準工作流的材質屬性以及描邊的顏色和寬度。

SubShader渲染標籤

Tags { "RenderType"="Opaque" "Queue" = "Transparent-1"}
LOD 200

渲染類型為不透明。

渲染隊列之所以設置為Transparent,是為了避免被天空盒擋住;而最後減1是為了保證是在Transparent之前被渲染。

第一層——描邊層

Pass
{
ZWrite Off

CGPROGRAM
#pragma vertex vert
#pragma fragment frag

struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};

struct v2f
{
float4 vertex : SV_POSITION;
};

fixed4 _OutlineColor;
fixed _OutlineWidth;

v2f vert(appdata v)
{
v2f o;
v.vertex.xyz += v.normal * _OutlineWidth;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}

fixed4 frag(v2f i) : SV_Target
{
return _OutlineColor;
}

ENDCG
}

在頂點著色器裏,我們把頂點坐標向著法線方向擴展,通過_OutlineWidth變數控制擴展的距離。

在片元著色器裏,直接返回_OutlineColor變數的顏色,這樣我們就可以看到膨脹之後的純色效果了。

為了避免膨脹之後的效果擋住接下來的正常效果層,我們把這一pass的深度寫入關閉。

第二個層——正常效果層

CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf StandardSpecular fullforwardshadows

// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0

struct Input
{
float2 uv_Albedo;
};

sampler2D _Albedo;
sampler2D _Specular;
sampler2D _Normal;
sampler2D _AO;
sampler2D _Emission;

// Add instancing support for this shader. You need to check Enable Instancing on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)

void surf (Input IN, inout SurfaceOutputStandardSpecular o)
{
fixed4 c = tex2D (_Albedo, IN.uv_Albedo);
o.Albedo = c.rgb;
o.Alpha = c.a;

fixed4 specular = tex2D (_Specular, IN.uv_Albedo);
o.Specular = specular.rgb;
o.Smoothness = specular.a;

o.Normal = UnpackNormal(tex2D (_Normal, IN.uv_Albedo));
o.Occlusion = tex2D (_AO, IN.uv_Albedo);
o.Emission = tex2D (_Emission, IN.uv_Albedo);
}
ENDCG

這一層是完整Specular工作流的表面著色器,我們也可以根據需要使用頂點-片元著色器。

最終效果

最終效果

推薦閱讀:

相關文章