UnityにあるURP Decal Projector使ってみた

# Decalとは
ゲームではよく使われている表現の一つです。

MMOゲームでは強キャラが溜めて攻撃する時などに、赤いエリアで染まっていく表現などをよく見ます。
それ以外でも、FPSゲームでは銃弾が当たったところに弾痕が残ったり、アクションゲームだと強い攻撃をしたときに地面にヒビなどが入ったりする表現などは誰もが見たことがあると思います。

それらの表現はDecalシェーダーで表現されている（することができる）ことがほとんどです。

ですが計算が複雑だったり、実装方法などを紹介している人も少ないので、忘れられがちな技術でもあります。

# URP Decal Shaderとは
Unityの2021.2から、シェーダーグラフというノードベースでシェーダーを作成できる機能のテンプレートにDecalShaderGraphが追加され、同時にそれを使用するためのDecal Projectorも追加されました。

**※この記事は、URPやHDRP、シェーダーグラフなどの知識がある前提で話を進めています。**
　**できるだけわかりやすく説明しますが、わからない単語などは調べていただければと思います。**

このDecal ShaderはURPとHDRPの両方にありますが、大きな違いとしてはHDRPは半透明オブジェクトにも投影が可能ということです。

# 使ってみた
次に簡単な説明をしながら実際に投影してみたいと思います。
## 0.環境
Unity ver. 2021.2.17f1
URPパッケージ ver. 12.1.6

## 1.準備
### デカール機能の追加
まずは、URP対応のシーンにデカール機能を追加する必要があります。

下の画像のようにURP対応のシーンには必ずUniversal Renderer Dataというものが使われています。
（プロジェクトを作成する際にURP対応のプリセットで作成していると、Foward Rendererという名前になっています。）

詳細は省きますが、ここに様々な描画オプションを追加することによって見た目のクオリティを上げることができ、Decal機能もその一つです。

下画像の赤丸のボタンからDecalを選んで追加、青丸のチェックが付いていることを確認してください。

※中の設定の説明は省きますが、Max Draw Distanceに関しては数値を上げておかないとカメラから遠くなると描画されなくなるので注意してください。

![デカール3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/ff32d527-d9f0-c3f1-fbe1-825d8e31eb3d.png)

### 投影するDecal Projectorの作成
次にDecal Projectorを作成します。

HerarchyからCreate > Rendering > URP DEcal Projectorをクリックして作成できます。
デフォルトだと真っ白な画像が投影されるようになっています。

※忘れてたけど投影されるオブジェクトも置くように

![デカール6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/d30ecc12-5c0d-b79d-dc36-96970e3470b6.png)

### マテリアルとシェーダーの作成

次は投影するためのマテリアル、は簡単に作れるのでマテリアルの設定を後で細かく変更できるようにシェーダーグラフを作ります。
Projectで右クリック Create > Shader Graph > URP > Decal Shader Graphをクリック（階層深すぎだろ！！）

![デカール11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/3e8219a0-d03f-0bd8-6d82-97879e1fa85a.png)

シェーダーグラフはノードと線をポチポチしているだけでなんとなくできるので楽しいです。
今回必要な最少構造は下画像のようになっています。

・texはInspectorで設定できる変数で、それを色情報と透過情報に渡しています。
・ゲーム系の知識ある人ならわかると思いますが、RGBが色情報でA(Alpha)が透明度情報です。
・UVは簡単に言うと描画の座標です。これをいじると歪ませたりできますが今回は省略です。

![デカール2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/096dd811-d2fc-abf4-e4b8-16103dea4d5e.png)

## 2.設定
### Decal Projectorの設定
プロジェクターを作成した時に白い線が出たと思いますが、それを投影されるオブジェクトにめり込むよう配置してください。
下画像のように、白い矢印を投影されるオブジェクトに向けると、白い枠線の中が白く投影されます。

![デカール14.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/069cf13e-42a2-effb-430d-9ac934fc48e7.png)


Decal Projectorのパラメーターを簡単に説明します。
|名前 |説明|
|:--| :--|
|Scale Mode |ScaleInvariant：下で設定した大きさを描画範囲とする <br>Inherit from Hierarchy：オブジェクトのScaleを描画範囲とする|
|Width  |横の大きさ  |
|Height  |縦の大きさ  |
|Projection Depth|奥行の大きさ  |
|Pivot|描画範囲の原点  |
|Material|設定するマテリアル、さっき作ったものを入れる  |
|Tilling|画像のタイル数、画像をRepeatにしてないと意味ないです。  |
|Offset|画像の描画位置、そんなにいじることないかも。  |
|Opacity|全体的な透明度  |
|Draw Distance|カメラからの描画距離、Depthより長くてもはみ出しません。  |
|Start Fade|この値の割合からDraw Distanceの距離までの間をフェードします。 <br>下画像だと、900から透過していき、1000で完全に透明化します。  |
|Angle Fade|なんかいじれないけど後で使います。 |

![デカール4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/1165f7fa-8342-9d63-1fd8-35aef09fec2c.png)

### 描画確認！

先ほど作ったシェーダーをマテリアルに割り当てて、Decal用の画像をネットとかから拾ってきてそれを設定します。
そのマテリアルをURP Decal ProjectorのMaterialを入れると描画されます。

![デカール5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/ba3b71d4-1227-3ad4-e180-01d6604771a5.png)

壁がはがれたような表現ができた！ヤッターーーー！
![デカール7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/b36489b4-5942-86ae-9bcd-2e98c685b771.png)

**？？？？？？？？？？？？？？？？？？？？？？？？？？？？？？？？？？**

動かしてみたらなんかすごい伸びた...。なぜかガンツを思い出してしまった。
どうやらめり込ませた中身は角度関係なく描画するようです。

### 修正
ここでさっきいじれなかったAngle Fade の出番のようです。

シェーダーグラフの設定を変えると使えるようになるっぽいです。
下画像、シェーダーグラフをいじる画面のデフォルト右上にあるGraph Inspector から
Graph Settings > Angle Fadeにチェックを入れます。

![デカール.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/111a618b-1c23-14db-1007-29b651ffac9e.png)

シェーダーグラフをセーブしてDecal Projectorを見ると変更できるようになってました。
あんまり見たことないスライダーなので簡単な説明をします。

下画像のように左右の半円を動かせるようになり、その間が太くなります。
これは太い部分の値をグラデーションしながら描画する設定になっており、比較対象は描画する場所の法線との角度です。

ちょっと難しくなりますが、Decalの描画方向と投影される面の法線方向のなす角とAngleFadeの値は、0~180の割合で一致しています。

|角度|0°|90°|180°|
|:-:|:-:|:-:|:-:|
|Angle Fade|左端|真ん中|右端|

今回の場合だと、描画方向とほぼ対面に向き合っている面だけ描画したいので、スライダーを真ん中より左寄りに移動します。

![デカール12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/3006c3c1-c885-a837-9b78-4b9bb302a607.png)

結果として横が伸びることは無くなりました！

![デカール9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/4b7109d1-2caa-5a7b-a6fa-31085f9acbdb.png)

## 3.応用
### その1.汚れたステッカー
10分くらいで作ったものです。
DecalシェーダーにはMetallicやSmoothnessなどが設定できるので、金属のような質感も表現できます。
複数のDecalと組み合わせることで汚れなどの質感も重ねて表現することも可能です。

![デカール13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/dc65c730-9825-d6da-72c3-2ae2ec373c31.png)


### その2.某ゲーム海
もうほとんどDecal関係ない気もしますが...
海の中に光のようなものがあるだけでより自然に見えます。

ちなみに海もShader Graphだけで作成しました。
HLSLで作ったこともありますが、ノードベースの方が簡単に作れました。

![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/ccb35156-31ff-0ebb-9548-e6d2c3dbfe4b.gif)




### その3.某ゲームウルト
Decal Projectorを触るきっかけですね。結構強キャラです。
エフェクトに関しては何回見てもよくわかりませんでした。

![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325647/b8f323ff-79c7-994f-481e-f35197adb543.gif)


## まとめ
現状は一方向にだけ描画する感じなので自由度はそこまで高くありませんが、演出のちょっとしたエッセンスになりますし、使う人が増えれば新しい使い方も見つかるはずなので、Unityを触るときに一度は使ってみることをおススメします。

今回使用した画像は下記サイトからダウンロードしました。結構便利なので愛用してます。（一部の画像は自作です）

https://www.textures.com/

私も今後パーティクルやシェーダー、VFXなどと組み合わせて高度な表現ができるように頑張ります。
完成したり新しい知見を得られたらまた投稿しようと思います。