今回はオブジェクトを地面にぶっさしで配置した際、地面のテクスチャとブレンドさせて違和感ない見た目にするシェーダーの作り方を解説します。
目次
作例:砂に埋まったオブジェクト
今回は作例として、砂に埋まったオブジェクトを表現してみましょう。
必要なのは、「地面に近い位置に」「地面のテクスチャが」「グラデーションで」見えるシェーダーです。
順番に考えてみましょう。
1.地面に近い位置を取得する
まずは地面に近い位置を判別し、それをマスクとする方法です。
今回は、DistanceFieldという機能を利用してみましょう。
DistanceFieldとは、近くにあるメッシュ同士の距離が白黒のマップとして表現されたものです。
細かい説明は公式ドキュメントにお任せし、ざっくりとした説明で進めてゆきます。
DistanceFieldを利用するための事前準備
まずはじめに、Mesh Distance Fieldを生成します。
画面左上、編集>プロジェクト設定から「Mesh Distance Field」と検索し、「メッシュ距離フィールドの生成」にチェックを入れます。

次に、色を変えたいオブジェクトの詳細パネルから[Affect Distance Field]のチェックを外します。

DistanceFieldはどのオブジェクトからの距離を測るかを設定することができるのですが、
ここがTrueに設定されていると、自分自身のメッシュも計算対象にいれて距離を算出してしまうため結果が正しく出なくなってしまいます。
地面からのみ影響を受けたいので、地面オブジェクトはTrue、突き刺すオブジェクトはFalseにしておきましょう。
以上で準備は完了です。
シェーダーを作る
今回はこの、ただ黒い箱を地面にぶっさします。


もちろんですが、地面との境目がはっきりと見えます。
これは不自然ですね。
試しに[DistanceToNearestSurface]をベースカラーにつないで確認してみましょう。
今回は色の変化がわかりやすいよう、にじませとコントラストの強弱をつける演算ノードも追加しました。


このように、地面に近い部分のみ黒く表示されるようになりました!
これで地面の近くを判別できるようになりました!
次に、地面テクスチャを見せる方法を考えます。
2.地面テクスチャをグラデーションで見せる
黒い部分に地面テクスチャを表示させる方法は2パターン考えられます。
・地面のテクスチャをマテリアルに追加してブレンドさせる
・黒い部分を透明にして透けさせる
今回は軽量化を考え、後者の透けさせる方法をとります。
(前者は複数種類のテクスチャをマテリアル内に持つことになるので処理が重いです)
これは簡単で、先ほど作ったマスクを透明度のパラメータとして利用すれば地面に近い部分が透けますね。
ただ今回は軽量シェーダを作るため、ディザリングという方法を利用します。
CutOffマテリアルでTranslucent マテリアルのようなグラデーションを作るための方法で、
疑似的なグラデーションを白黒の点描(モザイク)で表現するものと考えておくとわかりやすいかもしれません。
一つ一つの点は100%の白と黒ですが、それでもグラデーションを作ることができます。
では機能実装してゆきましょう!

マテリアルのBlendModeをMaskedに変更すると上の図のように[オパシティマスク]に接続することができるようになります。
[DitherTemporalAA]を呼び出し、上で作ったマスク用のノード群に接続します。
出力先は[オパシティマスク]に接続してあげましょう。

このように、地面の近くが透けるようになりました!よく見ると純粋なグラデーションではなく点で構成されているのがわかります。
グラデーションにはなりましたが、きれいに横一列になっているのが気になりますね。少し乱しましょう。

今回は上の図のようにノードを配置し、グラデーションにノイズをかけてみました。
こちらのテクスチャはエンジンのコンテンツから利用しました。利用方法についてはこちらの記事で解説しました。

不均一になりました!だいぶ砂っぽくなじみましたね!

上のように複製して適当に埋めるだけで砂に埋まった風の表現ができます。
まとめ

以上、簡単なノードでぶっさしのオブジェクトをなじませてみました!
今回は砂に埋まったものでしたが、草地や水辺でも使える便利なシェーダーなのでぜひお試しください!