[UE4] Decalの延びを何とかしたい

検証UE4: 4.27.1


#はじめに
デカールはEnvironmentsのディティールアップ、また着弾爆発のようなゲームの演出としても非常に効果的です。
しかし、UVは2Dなので高さ方向のテクスチャが延びて見えてしまう傾向にあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/7ef7dcde-189f-3db2-efcf-ca9425c5d71f.png)
ちょっと格好悪い……何とかしたい……
Decal扱う人が通る道かと思うので、どっかに良い解決策があるかもしれません。あったら教えて下さい。

##参考
- UE4のDecalを掘り下げる - Qiita
    - https://qiita.com/dgtanaka/items/cefe8575b0a8337c3e42
- Valorant decals approach - REAL-TIME VFX
    - https://realtimevfx.com/t/valorant-decals-approach/13160/5
        - 何か考えよう、と思っていたらスレッドが有りました。今回主にここから引用しています。
- Fix Decal stretching in Unreal 4 - Youtube
    - https://www.youtube.com/watch?v=TDhYQt3WKKo
        - 色んな手法で解決している動画

#（タイリング用）法線方向でUVを補間する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/7153d9aa-2950-27a6-0e62-371e55227789.png)

こちらのコースティクスで実装されていました。Thanks Ben.
Water Caustics - UE4 Materials 101 - Episode 27 - Youtube
<iframe width="560" height="315" src="https://www.youtube.com/embed/9z6EMsoqLDY?start=1038" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

各面方向に展開したUVを、法線方向から補間して使用しています。
いい感じだと思いました。
UVで対処してテクスチャサンプリングが１つという事で、円柱辺りに少し境目が見えてしまっているでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/b00a3da7-98de-3650-e2ee-59866d63256c.png)


##実装
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/6f83fa6b-4e4c-a470-ce4c-0cdce80b8d40.png)
※DBufferでは「SceneTexture:WorldNormal」が取得出来ない為、後述の代替を試してください。→[DBufferでシーン法線を使いたい](#DBufferでシーン法線を使いたい)

#（タイリング用）WorldAlignedTextureで3Dマッピング
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/5a831141-2a3d-a57e-3b02-cbea07e6aae7.png)

ノードが用意されているので、一番簡単な手法です。
ワールドXY平面、YZ平面、XZ平面でそれぞれテクスチャサンプリング。後は法線方向でブレンドします。
一つ前のはUVを補間、こちらはテクスチャサンプルの結果を補間しているのが違いです。

恐らくタイリングを用いる方法では一番綺麗なのかな、と思います。
ただ、テクスチャサンプリングを３回行う都合上、描画負荷が高くなる傾向にあります。

##実装
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/ad0d0a81-5751-4d41-aad0-4db78e3a3711.png)
WorldAlignedTexture関数はUE4デフォルトで用意されています。
※DBufferでは「SceneTexture:WorldNormal」が取得出来ない為、後述の代替を試してください。→[DBufferでシーン法線を使いたい](#DBufferでシーン法線を使いたい)

#角度によって消す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/15750312-48bb-5561-9157-3dd4b2b90dd9.png)

こちらで紹介されていました。Thanks Tobias.

- ANGLE BASED FADE OUT - TOBIAS NOLLER
    - https://tobiasnoller.com/angle-based-fade-out/

配置したデカールから一定角度以上の所は非表示にして、延びている所を消してしまう方法です。
実装は手軽で格好悪い所を消せるので、ひとまずこれで実装して様子見るのがいい感じがします。
僕も過去、同じような方法で対処した事あります。
デメリットとしては、段差とかで若干不自然に見えたりする事でしょうか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/f261a2ea-4b06-8008-ad6c-c2b2002142ae.png)

##実装
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/40d0313f-3285-2e62-2070-861f115f9fc5.png)
DDX,DDYの下りは法線を取得しています。→[DBufferでシーン法線を使いたい](#DBufferでシーン法線を使いたい)参照
その法線から一定角度をオパシティで非表示にしています。

#球状に展開する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/422053c1-f3be-263a-380b-30adaae5f29b.png)
記事書きながらあれこれ考えてたらちょっとマシな感じになりました。
DecalComponentのZ軸座標から離れるほどUVを縮小してみました。
球状（というよりは三角形状）にUVをスケールしています。
実際のシーンなりで確認していないので、何かしら粗があるかもしれません。
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Decal Component test. no stretch uv. <a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://t.co/omIRmH1toH">pic.twitter.com/omIRmH1toH</a></p>&mdash; com04 (@com04) <a href="https://twitter.com/com04/status/1469723759577755653?ref_src=twsrc%5Etfw">December 11, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##実装
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/43fea486-9860-db94-016d-2b87c9a2128e.png)
今はXY平面に配置する前提で組んでますけど、壁に撃った銃弾とかはいい感じに軸変えて計算すればいけるかも。試してないです。


#ほか
##DBufferでシーン法線を使いたい
WorldPositionからDDX,DDYを使うことで算出できるようです。
（ちょっと勾配関数詳しくないので間違ってたらごめんなさい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/328b8bd2-cf72-ef7f-1902-d3a168a932d3.png)
SceneTextureを参照しないのでDBufferでも使えます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58518/a65561b4-3394-33dc-5577-81e6f5cbb209.png)