【UnityShader】テクスチャのブレンド #13
前回の成果
uvスクロールができるようになった。
今回やること
テクスチャのブレンドをしていきます!
事前準備
SecneにPlaneを置いて、カメラから見えるようにしてください。
テクスチャのブレンドでは、
- メインテクスチャ
- サブテクスチャ
- Mask画像
の3つが必要となるので用意してください。
今回使用した画像サイト様です。
メインテクスチャ publicdomainq.net
サブテクスチャ frame-illust.com
マスク画像 tearslabnscr.blog.fc2.com
ソースコード
Shader "Custom/textureBlend" { Properties { _MainTex ("Main Texture", 2D) = "white" {} _SubTex ("Sub Texture", 2D) = "white" {} _MaskTex ("Mask Texture", 2D) = "white" {} } SubShader { Tags { "RenderType" = "Opaque"} LOD 200 CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 struct Input { float2 uv_MainTex; }; sampler2D _MainTex; sampler2D _SubTex; sampler2D _MaskTex; void surf (Input IN, inout SurfaceOutputStandard o) { fixed4 mainPixel = tex2D (_MainTex, IN.uv_MainTex); fixed4 subPixel = tex2D (_SubTex, IN.uv_MainTex); fixed4 mask = tex2D (_MaskTex, IN.uv_MainTex); o.Albedo = lerp (mainPixel, subPixel, mask); } ENDCG } FallBack "Diffuse" }
今回行なっていることは、各テクスチャのピクセルの色情報を元に、Albedoを変更しているように見えます。
マスク画像
マスク処理は、特定の部分のみを表示(抽出)し、それ以外の部分を表示しない(黒色画像または白色画像)ようにする画像処理のことをいいます。
マスク処理を行うためには、表示(抽出)したい部分は、どこなのかを表す基準画像をあらかじめ用意する必要があります。:リモートセンシング画像処理>マスクより引用
とあります。
今回の場合では、特定の部分のみ抽出したいのでこのマスク画像を使用します。
今回はこのような
くっきりとしたマスク画像ではなく、徐々に変化していくマスク処理を行いたいため、マスク画像をこのような
少しぼやけた画像にしています。
ぼやけた画像にすることによって、その明度からメインテクスチャとサブテクスチャのブレンドをする割合を調整することができます。
これは以前行なったグレースケールと同じです。
グレースケールについてはこちらを参照してください。
Lerp
この関数はTimeと同じでShader側で予め定義されている関数になります。
これは数学の線形補間と同じもので、
// start ... 始点 // end ... 終点 // time ... 割合 lerp (start, end, time);
となっています。
timeで、startとendの間を補間し、timeは0~1の範囲に固定されています。
この0~1というのは、startを0、endを1として、現在の割合を示しています。
これを利用して、メインテクスチャとサブテクスチャの割合をグレースケールで補間しています。
アタッチ
Scene上においた、Planeに対して、今回制作したShaderをアタッチします。
そして、
上の図のように、
- Main TextureにレンガのTexture
- Sub Textureに模様のTexture
- Mask Textureにマスク画像
をアタッチしてください。
今回の成果
マスク画像のように合わせてテクスチャのブレンドができました。
+α
このテクスチャブレンドを時間によって変化させます。
上記のソースコードのAlbedoの部分を
o.Albedo = lerp (mainPixel, subPixel, mask);
このように、* abs(_SinTime.w)を追加します。
o.Albedo = lerp (mainPixel, subPixel, mask) * abs(_SinTime.w));
こうすることで、
このように、時間によってテクスチャブレンドをしてくれるようになります。
どうしてこうなるのか
absは#7で行なった、絶対値のことです。
不明なのは、_SinTime.wの方だと思います。
SinTime
このSinTimeは時間の正弦のことを表しています。
名称 | 用途 |
---|---|
_SinTime.x | time/8 |
_SinTime.y | time/4 |
_SinTime.z | time/2 |
_SinTime.w | time |
Timeとは異なっているので、気をつけてください。
SinTimeは上記の緑色の線で示されている、0~1を往復する波(正弦波)を描きます。
このままだと、マイナスの値になってしまうので、abs関数を使用しています。
ソースコードにコメントを付与
Shader "Custom/textureBlend" { // プロパティ Properties { // メインtexture _MainTex ("Main Texture", 2D) = "white" {} // サブtexture _SubTex ("Sub Texture", 2D) = "white" {} // マスク画像 _MaskTex ("Mask Texture", 2D) = "white" {} } // Shaderの中身の記述 SubShader { // 一般的なShaderを使用 Tags { "RenderType" = "Opaque"} // しきい値 LOD 200 // cg言語記述 CGPROGRAM // フォワードレンダリング #pragma surface surf Standard fullforwardshadows // Shader Model #pragma target 3.0 // Input構造体 struct Input { // テクスチャのuv座標 float2 uv_MainTex; }; // メインtexture sampler2D _MainTex; // サブtexture sampler2D _SubTex; // マスクtexture sampler2D _MaskTex; // surf関数 void surf (Input IN, inout SurfaceOutputStandard o) { // メインtextureのピクセルの色 fixed4 mainPixel = tex2D (_MainTex, IN.uv_MainTex); // サブtextureのピクセルの色 fixed4 subPixel = tex2D (_SubTex, IN.uv_MainTex); // マスクtextureのピクセルの色 fixed4 mask = tex2D (_MaskTex, IN.uv_MainTex); // マスクの色から時間で変化するテクスチャブレンドをする o.Albedo = lerp (mainPixel, subPixel, mask * abs(_SinTime.w)); } // Shaderの記述終了 ENDCG } // SubShaderが失敗した時に呼ばれる FallBack "Diffuse" }
今回はこれで終了です。
ご視聴ありがとうございました!