【UnityShader】ノイズシェーダー拡張 【3】#47
前回の成果
ノイズを使用して着色した。
今回やること
ノイズシェーダーを使用して、歪ませます。
事前準備
Scene上にPlaneを配置し、今回制作したMaterialをアタッチします。
ソースコード
Shader "Unlit/DistortionNoise" { Properties { _MainTex ("Texture", 2D) = "white" {} _BaseColor ("Base Color", Color) = (1, 1, 1, 1) _AddAlphaColor ("Add Alpha Color", Color) = (0, 0, 0, 1) } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent"} LOD 100 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; fixed4 _BaseColor; fixed4 _AddAlphaColor; 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 { fixed4 col = tex2D(_MainTex, i.uv); col *= _BaseColor; col.rgb += _AddAlphaColor * col.a; return col; } ENDCG } } }
歪ませるために、まずはアルファブレンドのソースコードです。
特に難しいことはしていません。
アルファブレンド
テクスチャと、2色の色を用いてアルファブレンドを行います。
そもそもアルファブレンドとは、
アルファブレンドとは、二つの画像を重ね合わせ、各画素ごとに設定された透過度(アルファ値)に基いて合成すること。
のことでエフェクト等を扱うのに使用されます。
結果
Main Textureには、Unityのデフォルトで存在するDefault-Particleを使用しています。
プロパティ
描画結果
このアルファブレンドしたものを歪ませていきます。
ソースコード
Shader "Unlit/DistortionNoise" { Properties { _MainTex ("Texture", 2D) = "white" {} _BaseColor ("Base Color", Color) = (1, 1, 1, 1) _AddAlphaColor ("Add Alpha Color", Color) = (0, 0, 0, 1) _NoiseTilingOffset ("NoiseTex Tiling(x,y)/Offset(z,w)", Vector) = (0.1, 0.1, 0,0) _NoiseSizeScroll ("NoiseTex Size(x,y)/Scroll(z,w)", Vector) = (16, 16, 0, 0) _DistortionPower ("Distortion Power", Float) = 0 } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent"} LOD 100 Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "extensionNoiseUtil.cginc" struct appdata { float4 vertex : POSITION; float2 texuv : TEXCOORD0; float2 noiseuv : TEXCOORD1; }; struct v2f { float2 texuv : TEXCOORD0; float2 noiseuv : TEXCOORD1; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; fixed4 _BaseColor; fixed4 _AddAlphaColor; fixed4 _NoiseTilingOffset; fixed4 _NoiseSizeScroll; float _DistortionPower; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.texuv = TRANSFORM_TEX(v.texuv, _MainTex); o.noiseuv = TRANSFORM_NOISE_TEX(v.noiseuv, _NoiseTilingOffset, _NoiseSizeScroll); return o; } fixed4 frag (v2f i) : SV_Target { fixed3 dist = normalNoise(i.noiseuv, _NoiseSizeScroll.xy); dist = dist * 2 - 1; dist *= _DistortionPower; i.texuv += dist.xy; fixed4 col = tex2D(_MainTex, i.texuv); col *= _BaseColor; col.rgb += _AddAlphaColor * col.a; return col; } ENDCG } } }
extensionNoiseUtil.cgincを使用しています。
extensionNoiseUtil.cgincは以下にあります。
テクスチャを歪ませる
考え方
考え方はフローマップと同じです。
フローマップは以前やったので、詳しくはそちらを参照してください。
フローマップは以下の画像のように歪みます。
法線マップも傾きにより色が変わるので、これをフローマップのように扱うことによりノイズテクスチャを歪ませます。
UV値から法線マップを出す
今回は法線マップをフローマップとして扱います。
なので、extensionNoiseUtil.cgincで定義したnormalNoise関数を使用します。
normalNoise
これはノイズで法線マップを生成する関数です。
定義は以下です。
fixed3 normalNoise(fixed2 uv, fixed2 size) { fixed3 result = fixed3(perlinNoise(uv.xy, size), perlinNoise(uv.xy + fixed2(1, 1), size), 1.0); return result; }
パーリンノイズ関数(疑似乱数)を使用し、法線マップを生成しています。
2回目のパーリンノイズにfixed2(1, 1)を加算している理由は、
法線マップ的にXYで異なる乱数でないと、常に斜め右上か左下方向の面の傾きベクトルになってしまうからです。
パーリンノイズ関数は疑似乱数のため、同じ値を引数に持たせると同じ結果が帰ってきてしまいます。
ですので、適当な値として1を加算しています。
fixed(1 ,1)を足さなかった場合
fixed(1 ,1)を足した場合
範囲を変える
パーリンノイズ関数は、0~1を返す関数なので、-1~1にするために以下を行っています。
dist = dist * 2 - 1;
結果
以下のようになれば成功です。
プロパティ
結果
また、プロパティの値を変更することによりエフェクトに幅を持たせることができます。
ソースコードにコメントを付与
Shader "Unlit/DistortionNoise" { Properties { _MainTex ("Texture", 2D) = "white" {} _BaseColor ("Base Color", Color) = (1, 1, 1, 1) _AddAlphaColor ("Add Alpha Color", Color) = (0, 0, 0, 1) _NoiseTilingOffset ("NoiseTex Tiling(x,y)/Offset(z,w)", Vector) = (0.1, 0.1, 0,0) _NoiseSizeScroll ("NoiseTex Size(x,y)/Scroll(z,w)", Vector) = (16, 16, 0, 0) _DistortionPower ("Distortion Power", Float) = 0 } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent"} LOD 100 Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "extensionNoiseUtil.cginc" struct appdata { float4 vertex : POSITION; // テクスチャ用UV float2 texuv : TEXCOORD0; // ノイズ用UV float2 noiseuv : TEXCOORD1; }; struct v2f { float4 vertex : SV_POSITION; // テクスチャ用UV float2 texuv : TEXCOORD0; // ノイズ用UV float2 noiseuv : TEXCOORD1; }; sampler2D _MainTex; float4 _MainTex_ST; fixed4 _BaseColor; fixed4 _AddAlphaColor; fixed4 _NoiseTilingOffset; fixed4 _NoiseSizeScroll; float _DistortionPower; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.texuv = TRANSFORM_TEX(v.texuv, _MainTex); o.noiseuv = TRANSFORM_NOISE_TEX(v.noiseuv, _NoiseTilingOffset, _NoiseSizeScroll); return o; } fixed4 frag (v2f i) : SV_Target { // パーリンノイズの疑似乱数からフローマップに見立てた法線マップを生成 fixed3 dist = normalNoise(i.noiseuv, _NoiseSizeScroll.xy); // distを-1 ~ 1の範囲に dist = dist * 2 - 1; dist *= _DistortionPower; i.texuv += dist.xy; fixed4 col = tex2D(_MainTex, i.texuv); col *= _BaseColor; col.rgb += _AddAlphaColor * col.a; return col; } ENDCG } } }
今回は以上となります。
ここまでご視聴ありがとうございました。