UE4 CustomDepth についてのメモ

# 概要
カスタムデプスについての基本メモ。
壁の向こう側にいるオブジェクトの表示のテストをします。


## 更新履歴
| 日付 | 内容 |
|:----|:-----|
|2023/01/17|初版|


## 参考
以下の記事を参考にいたしました、ありがとうございます。
[UE公式：ポストプロセスマテリアル](https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/PostProcessEffects/PostProcessMaterials/)
[【UE4】CustomDepthの基本の備忘録](https://argonauts.hatenablog.jp/entry/2021/04/29/175549)
[【UE4】複数のポストプロセスを使い分ける](https://kinnaji.com/2019/01/08/customstencil/)


## 環境
Windows10
Visual Studio 2017
UnrealEngine 4.26.2


# CustomDepth
ステルスゲームなどでよくある壁の後ろにいるオブジェクトの色付き表示をやってみます。

### レンダリング設定
対象となるアクターのメッシュコンポーネントのレンダリング設定[Render CustomDepth Pass]にチェックを入れる。
これでこのオブジェクトはカスタム深度バッファに値がはいるようになります。
![RenderPassSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/ae79c1a6-78f6-9cf2-386f-c10547696fae.png)


### マテリアル作成
次にマテリアルを新規作成し、設定からマテリアルの [Material Domain] を [Post Process] に変更。
![MT_Setting1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/ed51bdb3-2021-ae9a-767d-852c6350dcc0.png)

ポストプロセスマテリアルの [Blendable Location] を [Before Translucency] に変更。
![MT_Setting2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/a2f126b9-7d48-b268-4314-56b4f1a678c9.png)

次にマテリアル処理を作成します。
シーンテクスチャからシーンデプス(通常の深度)とカスタムデプス(設定したメッシュのみの深度)から差分を比較し、オブジェクトの後ろにいるかを判定し、色を変えるようにします。

![MyCustomDepth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/600f8f7d-6615-e334-fe03-d2a9843c3799.png)



### ポストプロセス設定
ポストプロセスボリュームのレンダリング機能から[ポストプロセスマテリアル]に先に作ったマテリアルを追加。

![PostProcessSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/d825cb65-b33f-4d76-d2ce-2eb12c532727.png)


### 結果

__▼ポストプロセス適用前__
![Base.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/fbf9eaf5-82bc-4e51-1d17-f4df14f5e25d.png)

__▼ポストプロセス適用後__
![Result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/2cbcf545-0292-067f-e984-06acd43bd547.png)



# CustomStencil
前述の方法ではオブジェクト毎の色替えができないため、カスタムステンシルを使ってオブジェクト毎の色替えをしてみます。

### プロジェクト設定＆レンダリング設定
[編集] -> [プロジェクト設定] -> [エンジン/レンダリング/ポストプロセス] の[カスタム深度ステンシルパス] を [Enabled with Stencil] に変更。

![ProjectSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/9f325022-eabf-aa2d-7883-c00b6216d6e8.png)

対象となるアクターのメッシュコンポーネントのレンダリング設定の[CustomDepth Stencil Value]に値を設定。
![StencilSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/ac3afe3a-9a71-b5cb-e71d-31e313a274ee.png)

[表示モード]->[バッファの可視化]->[カスタムステンシル]で値の確認ができます。
![Buffer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/a8bb7400-e27a-b0ff-f06c-13608c1e2275.png)



### マテリアル作成
マテリアルを新規作成し、[Material Domain] を [Post Process] に変更、[Blendable Location] を [Before Translucency] に変更。

カスタムステンシル値が1の時(水色)と2の時(白)とそれ以外(緑)で色分けをする処理を書きます。
![MT_Stencil.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/8eb5b534-8131-762c-f303-5a2c2288d66f.png)

CustomDepthの時と同様に、ポストプロセスマテリアルに作成したマテリアルを適用します。

### 結果

カスタムステンシル値で色分けがされます。
![Result2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/afc11203-b7dc-7062-962e-3ec851301d0a.png)


# その他

### 関連C++コード
__▼プリミティブコンポーネント__
"Engine\Source\Runtime\Engine\Classes\Components\PrimitiveComponent.h"

__▼ポストプロセスボリューム__
"Engine\Source\Runtime\Engine\Classes\Engine\PostProcessVolume.h"
"Engine\Source\Runtime\Engine\Classes\Engine\Scene.h"

```cpp:PrimitiveComponent.h

class ENGINE_API UPrimitiveComponent : public USceneComponent, public INavRelevantInterface
{
	GENERATED_BODY()

public:

　　/** true の場合、このコンポーネントはカスタムデプスパスでレンダリングされます。(通常はアウトラインに使用)*/
	UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadOnly, Category=Rendering, meta=(DisplayName = "Render CustomDepth Pass"))
	uint8 bRenderCustomDepth:1;

　　/** カスタムデプスパスのステンシルバッファに0～255の値をオプションで書き込みます。(プロジェクト設定または r.CustomDepth == 3 が必要) */
	UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadOnly, Category=Rendering,  meta=(UIMin = "0", UIMax = "255", editcondition = "bRenderCustomDepth", DisplayName = "CustomDepth Stencil Value"))
	int32 CustomDepthStencilValue;

	/** Sets the bRenderCustomDepth property and marks the render state dirty. */
	UFUNCTION(BlueprintCallable, Category="Rendering")
	void SetRenderCustomDepth(bool bValue);

	/** CustomDepth ステンシル値 (0 ～ 255) を設定し、レンダリング ステートをダーティとしてマークします。 */
	UFUNCTION(BlueprintCallable, Category = "Rendering", meta=(UIMin = "0", UIMax = "255"))
	void SetCustomDepthStencilValue(int32 Value);

	/** CustomDepth ステンシル書き込みマスクを設定し、レンダリング ステートをダーティとしてマークします。 */
	UFUNCTION(BlueprintCallable, Category = "Rendering")
	void SetCustomDepthStencilWriteMask(ERendererStencilMask WriteMaskBit);

	/** bRenderInMainPass プロパティを設定し、レンダリング ステートをダーティとしてマークします。 */
	UFUNCTION(BlueprintCallable, Category = "Rendering")
	void SetRenderInMainPass(bool bValue);

};
```


# まとめ
ステンシルを使うと処理負荷が高くなるらしいので要注意です。