【Unity】シェーダーグラフで作るエフェクト用シェーダー:アルファと加算 ~後編~

f:id:Effect-Lab:20180618221816j:plain

 

こんにちは。

 

前回に引き続き、エフェクトを作るにあたって絶対に外せないアルファブレンドと加算ブレンドのシェーダーを、シェーダーグラフで作ってみたいと思います。
これがないと始まらないというような基本のシェーダーです。

 

前回の記事では下記の内容を解説しました。

  • テクスチャ1枚で制御する最もシンプルなアルファブレンドシェーダー
  • テクスチャ1枚で制御する最もシンプルな加算ブレンドシェーダー

 

今回の記事は前回の記事を読んでいる事を前提に書いていますので、まだの方は下記のリンクから御覧下さい。

 

 

この後編では下記のシェーダーの作り方を解説していきます。

  • カラーとマスクを別テクスチャで制御するアルファブレンドシェーダー
  • カラーとマスクを別テクスチャで制御する加算ブレンドシェーダー

 

記事の途中で「なぜテクスチャを別にするのか???」そのメリットデメリットにも触れてますので、興味のある方はそちらも合わせて御覧ください。

 

それでは後編、いきますっ! 

 

 

カラーとマスクを別テクスチャで制御するアルファブレンドシェーダー

今回はカラー用とマスク用の2枚のテクスチャを使用します。
用意したテクスチャは下記のテクスチャです。
それぞれアルファチャンネルは存在せず、Unity上ではDXT1となっています。

f:id:Effect-Lab:20180618225523j:plain

 

 シェーダー全体図

f:id:Effect-Lab:20180619005208j:plain

シェーダーの全体は上図のようになります。
ここから各ノードで何をしているのか、全体の流れを解説していきます。 

 

ただ、お気づきの方もいるかもしれませんが、前回解説したテクスチャを1枚使用するシェーダーとほとんど変わっていません。

 

カラーとマスクが別テクスチャに別れただけですからね。
ですのでサクッと行ってしまいますね。

 

 

 ① マスターノードの設定

今回作成するのはアルファブレンドですので、SurfaceTransparent(半透明)に、BlendをAlpha(アルファ)にします。

 

 

 ② カラーテクスチャを指定

ここではカラーテクスチャを指定しています。
マテリアルからテクスチャを差し替えられるように、「Texture 2D Asset」ノードを「Sample Texture 2D」ノードのTextureに繋ぎ、プロパティ化しています。

 

 

 ③ マスクテクスチャを指定

ここではマスクテクスチャを指定しています。
カラーと同様、マテリアルからテクスチャを差し替えられるようにしています。

 

 

 ④ パーティクルシステムからカラー(RGB)とアルファ(A)を編集できるようにする

ここも前回と同様、パーティクルシステムからカラーとアルファの値を編集できるように「Vertex Color」ノードを追加しています。

 

 

 ⑤ カラー用テクスチャと頂点カラー(RGB)をブレンドする

ここではカラーテクスチャと頂点カラーをブレンドしています。
そのあとマスターノードのColorに繋ぐことで、パーティクルシステムから色の変更が可能になります。

  

 

 ⑥ マスクテクスチャと頂点アルファ(A)をブレンドする

今度はマスクテクスチャと頂点アルファをブレンドし、マスターノードのAlphaに繋ぎます。
これでアルファチャンネル付きのテクスチャを使用した時と同様、マスクテクスチャに描かれた絵柄で画像が透過されます。

 

さて、ここのノードの繋ぎ方で1つ気になる点があります。
「Vertex Color」ノードを「Split」ノードでチャンネルを分割してアルファ(A)のみを抽出するところまでは前回と変わりませんが、「Sample Texture 2D」ノードの「R」から繋いでいるところに注目して下さい。

f:id:Effect-Lab:20180619012349j:plain

 

マスク用のテクスチャは白黒ですので、RGBのどのチャンネルも値は同じになります。
アルファは1チャンネルの0~1の値さえあれば機能しますので、Rの値のみ使っているという訳です。

 

  

これで今回のシェーダーは完成です。

f:id:Effect-Lab:20180619203841j:plain

 

 

なぜカラーとマスクでテクスチャを分けるのか???

さて、ここでそもそもなぜテクスチャを2枚に分けるのかを説明しておこうと思います。

 

前編で書いたように、アルファチャンネルにマスク用画像を含んだ1枚のテクスチャがあればエフェクトは作れますし、実際のゲーム開発でも普通に使われます。
ではなぜカラーとマスクで2枚のテクスチャに分けるかというと、メモリの節約とテクスチャの流用有効だからです。

 

はじめにメモリの節約について説明しましょう。

 

まず、下図のような3つのエフェクトを作るとします。

f:id:Effect-Lab:20180619212907j:plain

 

虹色の柄で、丸、ハート、星の3つの形のパーティクルを発生させています。
これらをマスク付きのテクスチャで作成すると以下の3枚のテクスチャが必要になります。

f:id:Effect-Lab:20180619221033j:plain

 


ここでさらに、同じ「丸、ハート、星」の形だけどストライプ柄のエフェクトが必要になったとします。

f:id:Effect-Lab:20180619214641p:plain

 

すると当然、新たに3枚のテクスチャが必要になります。

f:id:Effect-Lab:20180619221046j:plain



このように、6つのエフェクトを表現するためには全部で6枚のマスク付きテクスチャが必要になります。

f:id:Effect-Lab:20180619224849j:plain

 

この6枚のテクスチャ、よく見てみるとカラーは2種類しか存在していません。マスクも3種類だけですね。

 

このように、マスク画像をアルファチャンネルに含めたテクスチャだけでエフェクトを作成していくと、「同じ柄なのにマスク形状違い」とか、「同じマスク形状なのに柄違い」というテクスチャがいくつも増えてしまいます。

 

これではテクスチャのメモリサイズが無駄に多くなってしまいます。

 

ではテクスチャをカラー用、マスク用の2枚に分けるとどうでしょうか?

f:id:Effect-Lab:20180620004619j:plain

 

必要なテクスチャが5枚に減りました。

 

ここでテクスチャのメモリサイズを比べてみましょう。

 

まずはカラーとマスクを1枚で作成した場合です。
1枚の解像度は「256x256」で、「32bit」のtgaで計測しています。

f:id:Effect-Lab:20180621021138j:plain

 

次はカラーとマスクを分けた場合です。
1枚の解像度は同じく「256x256」で、アルファチャンネルを含まないので「24bit」のtgaです。

f:id:Effect-Lab:20180621021153j:plain

 

かなり減りましたね!
約40%のメモリが削減されました。

 

実際にゲームで使う際はここから圧縮や原色がされるので削減されるメモリサイズはこの限りではありませんが、メモリが節約できる事は確かです。

 

このように、カラー用とマスク用のテクスチャを別に分けておくと、テクスチャを流用してエフェクトを作成する際にメモリの削減に有効になります。

 

 

次にテクスチャの流用にどのように有効かを解説していきます。

 

まず1つ目に、メモリ削減の解説で説明したように、「同じ柄だけどマスクの形状違い」のエフェクトを作りたい場合、下図のように新たに同じ柄のカラーと形状違いのマスクを含んだテクスチャを作成する必要があります。

f:id:Effect-Lab:20180624113628j:plain


これが、カラーとマスクを別にしておけばカラーはそのまま流用できるので、マスクだけ新しく作るだけで済むので楽ですね。

f:id:Effect-Lab:20180622014951j:plain

 

 

2つ目に、下図のようなエフェクトを新しく作るとします。

f:id:Effect-Lab:20180622010213j:plain

 

このハートのパーティクルは加算ブレンドで作られていて、色はパーティクルシステムでピンクにしています。

 

この時、もし下の6枚のテクスチャしか無かった場合、カラーに虹色とストライプ柄が入ってしまっているのでこれらのテクスチャは流用できず、新たにカラーが白でマスクがハート型のテクスチャを作る必要が出てしまいます。
f:id:Effect-Lab:20180619224849j:plain

 

ではカラーとマスクを分けていた場合はどうでしょう? 
加算なので色の黒いところは自動的に透明になります。ですので、今回のエフェクトを作るにはハート型のマスク用テクスチャがそのまま流用できちゃいます。

f:id:Effect-Lab:20180622014449j:plain

 

エフェクトは、様々な素材をいろいろなエフェクトに使いまわす事が多いです。
マスク用に作ったテクスチャを、パーティクルシステムで色を付ける事を前提に、カラー用のテクスチャとして使い回す事も少なくありません。
そのため、このようにカラー用とマスク用を別テクスチャで用意しておくとテクスチャの流用がしやすくなり、いろいろなエフェクトを作りやすくなります。

 

以上がカラー用とマスク用でテクスチャを別ける事による主なメリットです。

 

良いことづくめのように見えますが、この方法にはデメリットもあります。
それは、1つのパーティクルに使用するテクスチャの数が増えてしまうことです。

 

パーティクル1つ1つに使用するテクスチャの数が増えれば増えるほど、そのパーティクルを描画する際の負荷は高くなってしまいます。
そのため、使用するテクスチャは出来るだけ少ないほうが良いです。

 

ただし、前述のメリットもあるため、負荷が高くなるからダメとは一概には言えません。
また、テクスチャ1枚でも複雑なシェーダーを作れば負荷は高くなりますし、負荷が高くてもパーティクルが画面に対して小さい範囲であれば負荷を抑える事も出来ます。

 

対象のプラットフォームやゲームのジャンル、エフェクトに対してどれだけパフォーマンスを確保するかで作り方は変わってくるため、この辺りはTAやプログラマさんと相談して、どのような作り方をしていくかを決めていく必要がありますね。

 

 

カラーとマスクを別テクスチャで制御する加算ブレンドシェーダー

さて、カラー用とマスク用でテクスチャを分ける理由を理解したところで、シェーダーの作成に戻りましょう。

 

次は加算ブレンドバージョンのシェーダーです。
使用するのはアルファブレンドの時と同様、カラーチャンネルのみの下記のテクスチャです。

f:id:Effect-Lab:20180618225523j:plain

 

 シェーダー全体図

f:id:Effect-Lab:20180619005243j:plain

シェーダーの全体は上図のようになります。
ここから各ノードで何をしているのか、全体の流れを解説していきます。 

 ① マスターノードの設定

今回は加算ブレンドですので、SurfaceTransparent(半透明)に、BlendをAddive(加算)にします。

 

 

 ②~⑥ 頂点カラーとテクスチャをブレンド

ここはアルファバージョンと同じです。

 

 

 ⑦ カラーとアルファを乗算してからマスターノードにつなぐ

ここがアルファバージョンとの大きな違いです。

 

前編でも解説したとおり、加算ブレンドのシェ-ダーはアルファが使えないため、マスターノードに繋ぐ前にテクスチャのカラーとアルファ、頂点カラーと頂点アルファのブレンドをここで全て済ましてしまっています。

 

以上で加算バージョンのシェーダーは完成です! 

f:id:Effect-Lab:20180624163522p:plain

 

 

 

 まとめ

今回はカラー用、マスク用のテクスチャ2枚を使ったアルファブレンドと加算ブレンドのシェーダーを作ってみました。

 

テクスチャ1枚を使った時よりも柔軟なテクスチャの流用が可能になってとても便利です。 

 

さて、これで前編と合わせてパーティクルの最も基本となるシェーダーが完成しました。
ただし、これだけでは普段皆さんが目にしているようなド派手でカッコイイエフェクトを作るには十分ではありません。

 

僕は今、エフェクト作成に必要な基本的なシェーダーをシェーダーグラフで用意しようと勉強中です。
また新しいのが出来たらブログに書こうと思いますので、それまでお待ち下さいね。

 

それでは、次回もお楽しみに!