【UnityShader】ブロックノイズトランジション #29
前回の成果
ワイプエフェクトを実装しました。
今回やること
トランジションをしていこうと思います。
トランジションとは
ビデオ編集する際に、カットとカットの間に挿入する切り替え効果のこと。
フェードイン、フェードアウト、ワイプ、オーバーラップなど、さまざまな効果がある。
ゲームでのシーン切り替えとかによくあるものです。
まず初めにブロックノイズのトランジションをしていきます。
事前準備
Scene上にCanvasを置き、その下にImageを置いてください。
次に、そのImageのMaterialに今回制作したMaterialをアタッチしてください。
最後にRect Transformを画面全体にstretchしてください。
ソースコード
Shader "Unlit/transitionBlockNoize" { Properties { _MainTex("Texture", 2D) = "white" {} _Color("Color", Color) = (1, 1, 1, 1) _Size("Size", Vector) = (1, 1, 0, 0) _Seed("Seed", int) = 0 _Value("Value", Range(0, 1)) = 0 _Smoothing("Smoothing", Range(0.00001, 0.5)) = 0 } SubShader { Tags { "RenderType" = "Transparent" "Quaue" = "Transparent"} Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _Color; int2 _Size; float _Seed; float _Value; float _Smoothing; float random(float2 st, int seed) { return frac(sin(dot(st.xy, float2(12.9898, 78.233)) + seed) * 43758.5453123); } v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { float2 st = i.uv * _Size; float2 i_st = floor(st); float sm = _Smoothing; float val = _Value * (1 + sm); float a = smoothstep(val - sm, val, random(i_st, _Seed)); fixed4 col = _Color; col.a = a; return col; } ENDCG } } }
以前やったブロックノイズに似ています。
floor
これは小数値の整数を返す関数です。
// xに整数値が欲しい数値を入れる floor(x); // 例 float a = 1.0f; float b = 3.5f; // 1が返ってくる floor(a); // 3が返ってくる floor(b);
smoothstep
これは指定した値を別の指定した値の範囲で収める関数です
// minに最小値、maxに最大値、xに収めたい値を入れる // x < minの場合は0、x > maxの場合は1、それ以外の場合は0から1の間で線形補間される smoothstep(min, max, x); // 例 float min = 0; float max = 10; float a = -3; float b = 5; float c = 12; // 0が返ってくる smoothstep(min, max, a); // 0.5が返ってくる smoothstep(min, max, b); // 1が返ってくる smoothstep(min, max, c);
smoothstepのイメージは下記の図です。
_Smoothing ("Smoothing", Range(0.00001, 0.5)) = 0
このPropertyを0ではなく、0.000001にしています。
これは、
smoothstep(val - sm, val, random(i_st, _Seed));
このsmoothstepのmin、max、xが全て0だった場合に0が返ってきてしまうためです。
下記の図のように、Valueが0にも関わらず画面が真っ黒になっていない箇所が出てきてしまいます。
Rangeが0のとき
Rangeが0.00001のとき
float random(float2 st, int seed)
これは、ブロックノイズの記事で紹介したようにランダムな値を返す関数となっています。
詳しくはこちらのサイト様を参考にしてください。
fragの解説
frag関数でやっていることの解説をしていきます。
float2 st = i.uv * _Size
uv値にsizeをかけることにより、1画面に何個ブロックノイズを出すかを決めています。
float val = _Value * (1 + sm);
この下でsmを引いているので、その調整のために足しています。
float a = smoothstep(val - sm, val, random(i_st, _Seed));
smを引いてあげることにより、ブロックノイズのAlphaを調整しています。
smが0の場合は、smoothstepのminとmaxが等しくなるため、Alphaは0か1になります。
結果
Valueを変化させることによって、トランジションしています。
ソースコードにコメントを付与
Shader "Unlit/transitionBlockNoize" { Properties { _MainTex("Texture", 2D) = "white" {} _Color("Color", Color) = (1, 1, 1, 1) // xとyにブロックノイズを表示する個数を入れる _Size("Size", Vector) = (1, 1, 0, 0) // シード値 _Seed("Seed", int) = 0 // ブロックノイズの値 _Value("Value", Range(0, 1)) = 0 // Alphaを許容する _Smoothing("Smoothing", Range(0.00001, 0.5)) = 0 } SubShader { Tags { "RenderType" = "Transparent" "Quaue" = "Transparent"} Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _Color; int2 _Size; float _Seed; float _Value; float _Smoothing; // ランダムな値を返す float random(float2 st, int seed) { return frac(sin(dot(st.xy, float2(12.9898, 78.233)) + seed) * 43758.5453123); } v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { // size分ブロックノイズを出す float2 st = i.uv * _Size; // 整数値を取得 float2 i_st = floor(st); float sm = _Smoothing; // 調整用 float val = _Value * (1 + sm); // Alphaをsmの値によって変化させる float a = smoothstep(val - sm, val, random(i_st, _Seed)); fixed4 col = _Color; col.a = a; return col; } ENDCG } } }
今回は以上となります。
ここまでご視聴ありがとうございました。