2017年10月21日 星期六

詳解火炬之光穿透剪影的效果(Silhouette or X Ray)

其實這個效果跟Shader沒什麼關係,基本上就是畫兩次,一次是畫剪影(Behind Pass),第二次是畫原本的模型(Original Pass),重點是Render State的設置…
以下是以Untiy Shader Lib為例:

Behind Pass的ZBuffer相關屬性設為:
ZTest Greater:意思是畫的時候,深度要大於目前畫面的深度值才畫,也就是被擋住的時候才
畫。
ZWrite Off:指的是不要寫入深度值,因為這個只是簡影,他跟目前畫面深度值是一樣
的。
基本上,這樣就差不多了,剩下的OgrinalPass就不多說了,因為這就是你原來的Shader Pass
啊!相關的範例Source Code如下:

Shader "Unlit/XRayExample"
{
Properties
{
_XrayColor("RimColor", Color) = (1.0, 0.0, 0.0, 1.0)
_MainTex("MainTex", 2D) = "white" {}
}
SubShader
{
LOD 200
Pass //behind pass
{
//render after opacity with alphaTest
Tags{ "RenderType" = "Transparent" "Queue" = "Transparent-20" }
ZWrite Off
ZTest Greater
Cull Back
Blend SrcAlpha One
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex VertexProgram
#pragma fragment FragmentProgram
struct VertexInput
{
float4 Vertex : POSITION;
};

struct VertexOutput
{
float4 Vertex : SV_POSITION;
};
uniform fixed4 _XrayColor;

VertexOutput VertexProgram(VertexInput Input)
{
VertexOutput Output;
Output.Vertex = mul(UNITY_MATRIX_MVP, Input.Vertex);;
return Output;
}
fixed4 FragmentProgram(VertexOutput Input) : SV_Target
{
return _XrayColor;
}
ENDCG
}
Pass //original pass
{
CGPROGRAM
#pragma vertex VertexProgram
#pragma fragment FragmentProgram
#include "UnityCG.cginc"

struct VertexInput
{
float4 Vertex : POSITION;
float2 UV : TEXCOORD0;
};

struct VertexOutput
{
float4 Vertex : SV_POSITION;
float2 UV : TEXCOORD0;
};
uniform sampler2D _MainTex;
half4 _MainTex_ST;

VertexOutput VertexProgram(VertexInput Input)
{
VertexOutput Output;
Output.Vertex = mul(UNITY_MATRIX_MVP, Input.Vertex);
Output.UV = TRANSFORM_TEX(Input.UV, _MainTex);
return Output;
}
fixed4 FragmentProgram(VertexOutput Input) : SV_Target
{
return tex2D(_MainTex, Input.UV);
}
ENDCG
}
}
}

相關的影片如下:



如果想模擬XRay顯示效果的話,在BehindPass加入Rim處理即可,相關的範例影片如下:



後記:其實在沒有Shader的時代,就可以利用multi pass及Render State來實作許多效果,好好利用SceneBlend、MultiPass及RenderState吧。

沒有留言:

張貼留言