このチャプターでは、以下のようなディゾルブ表現を作る方法を紹介します。
サンプルデータ
ディゾルブ表現のサンプルデータはGitHubにて公開中です
Assets/_SampleData/ShaderSamples/11_Dissolve
用意するもの
- ノイズテクスチャ
- 3Dモデル
ノイズテクスチャを3Dモデルに貼り付けた際、ノイズが偏りなく貼りついているのが理想です。
ノイズテクスチャの作成にはHoudiniを使用しています。 (作り方は後半で解説します)
ShaderGraphの設定
Alpha ClipをONにしておきます。
ディゾルブ表現の作成
手順1 : ノイズテクスチャの二値化
Stepノードでノイズテクスチャを二値化し、Emissionとして出力してみます。
結果
マテリアルのClip Timeを変化させると、モデルの表面がじわじわと白く塗りつぶされていきます。
手順2 : モデルを削る
ノイズの二値化パターンをAlpha Clip Thresholdに接続します。
0.5 < Alpha Clip Threshold になった場合にクリッピング(描画がキャンセル)されるため、
Stepの出力の白い部分がくり抜かれます。
結果
マテリアルのClip Timeを変化させると、モデルの表面が削れていきます。
手順3 : フチを光らせる
以下のように、削れるフチの部分を白く光らせてみましょう。
フチを光らせる
ノイズテクスチャの二値化でモデルを塗りつぶしつつ、時間を少し遅らせた二値化でモデルを削ります。
結果
削れのフチの部分が光ります。
問題点 : Clip Time = 1にしたときに削れが残る
今回作成したディゾルブ表現ですが、問題点があります。
Clip Time = 1としたときに、メッシュが削れきれずに残ってしまうのです。
実際のゲームで使いたい場合、Clip Time = 1 でメッシュが完全に削れた方が都合が良いでしょう。
メッシュが削れきれずに残ってしまう理由
ヨコ軸をClip Time、タテ軸をディゾルブの変化としてグラフに描いてみると、以下のようになります。
Clip Time = 1 の時、色の変化は完了していますが、メッシュは完全に削れずに少し残ってしまっています。
Clip Time = 1 で完全に削る
メッシュが削れ切れるのは Clip Time = 1.4 なので、Clip Time を 0 ~ 1 から 0 ~ 1.4 の範囲に変換してあげます。
範囲変換すると、以下のようなグラフになります。
ShaderGraph
Remapノードを利用して、Clip Timeの範囲を [0, 1] から、 [0, 1 + DelayTime] へ変換します。
結果
Clip Time = 1 の時にメッシュが完全に削れるようになりました。
応用 : 燃えるディゾルブ表現
燃えて消滅するようなディゾルブ表現の作り方を紹介します。
Rampテクスチャ
以下のRampテクスチャを使用して、燃えるような色の変化を与えます。
グラフ
このディゾルブ表現を時間のグラフとして表すと以下のようになります。
- ヨコ軸 : ClipTime
-
タテ軸 : ノイズテクスチャに含まれる明度(0~1)
実際の表示との対応は以下のようになります。
ShaderGraph全体
シェーダーグラフ全体は以下になります。
ノイズテクスチャにSmoothstepを適用した後、Rampテクスチャで着色しています。
Rampテクスチャを利用した着色方法は以下のチャプターで解説しています。
🍍 グレースケール画像に色を付ける
要素01 : カラーグラデーションの変化
以下の部分では、カラーグラデーションの変化を作っています。
時間経過で徐々に発光していくような色の変化
実際の変化
ClipTimeの値を増やしていくと、以下のように変化します。
要素02: グラデーションのマスク
Stepノードを利用して、ノイズの色がClipTimeを下回る部分を0にするようなものを作ります。
時間経過で徐々に白くなっていくような変化
実際の変化
画面上で確認してみると、以下のようになります。
要素01 × 要素02
要素01と要素02を乗算することで、徐々に輝き始めるという表現になります。
カラーグラデーションの変化を二値化パターンでマスクする
実際の変化
画面上で確認してみると、以下のようになります。
要素03 : メッシュ削れ
以下は、ノイズテクスチャの二値化をAlpha Clip Thresholdに接続して、メッシュが削れるようにしています。
実際の変化
要素01 × 要素02 × 要素03 (完成)
グラデーションの変化と、メッシュ削れを組み合わせると、発光したのちに削れて消滅するという表現になります。
ShaderGraph
ノイズテクスチャの作成 (Houdini)
Houdiniを使ったノイズテクスチャの作成方法を紹介します。
使用ツール
- Houdini 18.0 (Indieライセンス以上)
Houdiniでノイズテクスチャを作るメリット
通常、ノイズテクスチャを球体のようなテクセル密度に偏りがある3Dモデルに貼り付けると、
模様に偏りが生まれてしまいます。
2D Perlin Noise
Houdiniは、3次元座標からノイズテクスチャを作成できるため、偏りのないノイズを作ることができます。
3D Perlin Noise
また、Houdini上でもディゾルブ表現を作れるため、
Houdini上でディゾルブを確認しながらノイズを調整できるメリットもあります。
ネットワーク全体
今回作るネットワークの全体像になります。
メッシュの細分化
今回、作成したノイズを頂点カラーに持たせ、それをテクスチャとしてベイクするため、
高い解像度の頂点数が必要になります。
Remeshノードを利用してメッシュを細かく分割し、頂点数を増やします。
Remeshでメッシュを分割するとUVが汚くなるので、下流ではUV Textureノードを利用してUVを設定します。
Perlin Noiseの設定
Attribute VOPを使ってノイズを設定します。
Attribute VOPの中では
座標Pからパーリンノイズ(Anti-Aliased Noiseノード)を生成し、頂点カラーCdへ設定しています。
ノイズ範囲を 0 ~ 1 にする
UnityのShaderGraphでノイズテクスチャを扱う際、
ノイズ値の範囲は0 ~ 1になっていた方が都合が良いのですが、
Attribute VOPで作成したノイズの値は0~1の範囲に収まっていません。
Attribute Promote と Attribute Wrangle を利用して、ノイズを0~1の範囲に変換するようなロジックを組んであげます。
ノイズの最大・最小の取得
Attribute Promoteを使うことで、Cdアトリビュートの最小値・最大値を取得することができます。
最初のAttribute Promoteでは、Cdアトリビュートの 最小値(Minimum) を求め、Detailクラスに保存します。
アトリビュートの名前は Cd_min にしています。
2番目のAttribute Promoteでは、Cdアトリビュートの 最大値(Minimum) を求め、Detailクラスに保存します。
アトリビュートの名前は Cd_max にしています。
ノイズの範囲変換
Attribute Wrangle ノードにて、Cdを 0~1の範囲に収めるようなVEXコードを書きます。
// detailが持つCd_minアトリビュート を取得
vector min = detail(geoself(), "Cd_min", 0);
// detailが持つCd_maxアトリビュート を取得
vector max = detail(geoself(), "Cd_max", 0);
// Cd を 範囲(Cd_min ~ Cd_max)から 範囲(0 ~ 1)へ変換
@Cd = fit(@Cd, min, max, 0, 1);
結果
ノイズの色の範囲が0~1になり、以下のような見た目になります。
Houdini上でディゾルブ表現を確認してみる
Unityへデータを持っていく前に、Houdini上でディゾルブ表現を作ってみて、良い感じのディテールが出ているかを確認しておいた方が良いでしょう。
今回は、24フレーム かけてモデルが削れるようにしてみます。
// 頂点カラーが小さい部分はクリッピング(削除)
if (@Cd.r < chf("clip"))
removepoint(geoself(), @ptnum);
// 頂点カラーを戻しておく
@Cd = 1;
結果
Houdiniを再生すると、以下のようなディゾルブ表現になります。
ノイズのディテールを調整したい場合、ノイズのパラメータを調整します。
(Attribute VOP内の Anti-Aliased Noiseを調整します)
テクスチャ出力
ディゾルブ表現に使うノイズができたので、頂点カラーをテクスチャとして出力します。
Map Baker ノード
SideFX Labs の Map Baker ノードを使用することで頂点カラーをテクスチャとしてベイクできます。
(SideFX Labsはインストール直後のHoudiniには含まれていないため、自分でインストールする必要があります)
Map Baker の設定
Map Bakerは Gamma = 1.0 に設定します。 (1.0以外の値を入れてしまうと、テクスチャとしてベイクされるカラー情報に逆ガンマ補正の計算が入ってしまいます)
結果
ベイクが完了すると、以下のようなノイズテクスチャが出力されます。
テクスチャのインポート (Unity)
ディゾルブ表現に使うノイズテクスチャは、カラー情報ではないので、
ノイズテクスチャのsRGBのチェックを外しておきます。