專案中的轉場Shader
還算簡單的效果(但我花了好幾天才成功 :P)
想要自己嘗試的可以先試試看 =>
提示
教學
建立著色器和材質球
Create > Shader > Image Effect Shader
注意建立vertex shader的話frag uv會經過畫面轉換,但我們不需要所以建立image shader
建立一個UI Image,指定材質球
Shader 腳本
> 首先畫出UV空間
fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.uv, 0, 1);
}
> 使用 frac(取小數) 分割空間
Propertie
{
_MainTex ("Texture", 2D) = "white" {}
_Tiling ("Tiling", Range(5, 30)) = 10
}
float _Tiling;
fixed4 frag (v2f i) : SV_Target
{
return fixed4(frac(i.uv * _Tiling), 0, 1);
}
> 把分割空間打包成函式,保持乾淨,並保留一個return 值用於之後運算
使用 floor(無條件捨去) 取得tile 座標
float tileValue(float2 uv, out float2 tilest, out float2 tilePos)
{
tilest = frac(uv * _Tiling);
tilePos = floor(uv * _Tiling);
return 1;
}
fixed4 frag (v2f i) : SV_Target
{
float2 tilest;
float2 tilepos;
tileValue(i.uv, tilest, tilepos);
return fixed4(tilest, 0, 1);
}
> 寫一個隨機函式,將2D輸入轉為1D輸出
tileValue 回傳tile的隨機值
float Random2DTo1D(float2 input)
{
return frac(sin(input.x * 61.87 + 0.1) * cos(input.y * 78.84 + 5.6) * 137.35 );
}
float tileValue(float2 uv, out float2 tilest, out float2 tilePos)
{
tilest = frac(uv * _Tiling);
tilePos = floor(uv * _Tiling);
return Random2DTo1D(tilePos);
}
fixed4 frag (v2f i) : SV_Target
{
float2 tilest;
float2 tilepos;
float value = tileValue(i.uv, tilest, tilepos);
return value;
}
> 過濾器,做出敞開的效果
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Tiling ("Tiling", Range(5, 30)) = 10
_Filter ("Filter", Range(0, 1)) = 0.5
}
float _Filter;
float tileFilter(float2 uv)
{
float filter = lerp(-1, 1, _Filter);
return abs(uv.x - 0.5) * 2 + filter;
}
fixed4 frag (v2f i) : SV_Target
{
float2 tilest;
float2 tilepos;
float value = tileValue(i.uv, tilest, tilepos);
float filter = tileFilter(i.uv);
return filter;
}
> 但我們需要的是以tile為單位的過濾器,這樣才能做出格狀的消失
將tileFilter輸入改為以tile為單位
float tileFilter(float2 tilepos)
{
float filter = lerp(-1, 1, _Filter);
return abs(tilepos - _Tiling / 2) * _Filter + filter;
}
fixed4 frag (v2f i) : SV_Target
{
float2 tilest;
float2 tilepos;
float value = tileValue(i.uv, tilest, tilepos);
float filter = tileFilter(tilepos);
return filter;
}
> 將隨機加入過濾器
float tileFilter(float2 tilepos, float noise)
{
float filter = lerp(-1, 1 + noise, _Filter);
return abs(tilepos - _Tiling/2) * _Filter + filter;
}
fixed4 frag (v2f i) : SV_Target
{
float2 tilest;
float2 tilepos;
float value = tileValue(i.uv, tilest, tilepos);
float filter = tileFilter(tilepos, value);
return filter;
}
> 透明度混合
使用 saturate (限制數值在0~1的範圍),防止filter數值超出需要的範圍
並把 noise移進 saturate,讓隨機過濾的計算更正確
SubShader
{
Cull Off ZWrite Off ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
}
float tileFilter(float2 tilepos, float noise)
{
float filter = lerp(-1, 1, _Filter);
filter = abs(tilepos - _Tiling/2) * _Filter + filter;
filter = saturate(filter + noise);
return filter;
}
> 上色,將剛剛的過濾器設為透明度
Properties
{
_Color ("Color", Color) = (0,0,0,0)
}
fixed4 _Color;
fixed4 frag (v2f i) : SV_Target
{
float2 tilest;
float2 tilepos;
float value = tileValue(i.uv, tilest, tilepos);
float filter = tileFilter(tilepos, value);
fixed4 color = fixed4(_Color.rgb, filter);
return color;
}
> 使用step(根據閥值輸出0或1) 移除漸變,不需要的可以跳過這一步
float tileFilter(float2 tilepos, float noise)
{
float filter = lerp(-1, 1, _Filter);
filter = abs(tilepos - _Tiling / 2) * _Filter + filter;
filter = saturate(filter + noise);
filter = step(0.5, filter);
return filter;
}
搭拉~
至於在遊戲中使用的話,用C# 的material.setfloat修改 _Filter就行了
轉場就是把Image放大到擋住整個畫面而已
基本上就這樣,還想要甚麼延伸效果就自己研究吧 :P
這次是教學,和筆記不一樣,會再詳細一點
第一次寫教學,感覺配色沒選得很好 D:
有錯或有什麼建議歡迎提出~