📝

[UE5] 背景透過したカメラキャプチャ画像をUIに表示する

2023/04/17に公開

■ 概要

UnityだとカメラでRenderTextureに描画して映像をRawImageに張り付けてUIに表示することができました。同じことを、UnrealEngineでやりたかったのでそのメモ書きです。
(まだUnrealEngineに不慣れで用語などが間違っている可能性があります)

環境:Unreal Engine 5.1.1

■ 方法

手順1. カメラの出力先をRenderTargetにする
手順2. PostProcessマテリアルでMask処理して透過させる
手順3. UImageにRenderTargetを設定する

手順1. カメラの出力先をRenderTargetにする

1.1 RenderTargetを作成

まずは RenderTarget を作成します。名前を RT_Capture としておきます。

1.2 キャプチャ用カメラを用意

次に Scene Capture Component2D コンポーネントを用意し、RenderTargetを設定します。
(Blueprintにするかなど細かい構成については省きます)

SceneCaptureComponent2DのDetailsタブの Scene Capture を設定します。

  • TextureTarget:先ほど作成した RT_Capture を指定
  • Capture Source: Final Color (HDR) in Linear sRGB gamut を指定

この時点で作成した RT_Capture に描画されているのが確認できます。確認のためにCubeを仮置きしています。

手順2. PostProcessマテリアルでMask処理して透過させる

Mapに配置してみると背景が描画されてしまっています。背景を除いたCubeだけをキャプチャするようにします。

方針としては、Depthを使って指定した距離より近ければ描画するようにMask処理を行います。
Scene Capture Component2DにPostProcessマテリアルを設定し、ポストプロセス処理でカメラで描画した後のRGBAを加工することが可能なようです。

2.1 PostProcessマテリアルを作成

通常のMaterialを作成します。

2.2 マテリアルの設定をPostProcessにする

スクショのように設定します。BlendModeはOutput Alphaを有効にしてからでないと設定できません。

2.3 Mask処理

まずはカメラ画像のノードを用意します。 SceneTextureノードを作成し、Detailsタブの SceneTextureIdPostProcessInput0にします。
同様にして、SceneTextureIdSceneDepthにしたノードを用意します。

続いて、以下のようにノードを繋げます。StepノードでDepth値を2値化します。StepでMaskする距離の閾値を設定しています。あとはPostProcessInput0にこの値を乗算してMaskしてからEmissiveColorにいれます。Opacityには2値化した値をいれてMaskします。

2.4 PostProcessマテリアルをCameraに設定

SceneCaptureComponent2Dに設定するだけです。

RT_Capture(RenderTarget)を確認すると先ほど表示されていた背景が消えています。

手順3. UImageにRenderTargetを設定する

UserWidgetにて、Imageを作成し、RenderTargetを設定するだけです。透過されて表示されているのが確認できます。

なお、コードから設定する場合に、SceneCameraComponent2Dから取得できるのはUTextureRenderTargett2Dですが、UObjectにCastして以下のように渡すことで設定できます。

if (const auto& ResourceObject = Cast<UObject>(TextureRenderTarget2D))
{
	Image->SetBrushResourceObject(ResourceObject);
}

■ おしまい

これでUIに3Dモデルをぐるぐる回転させながら表示したりできるのではないかと思います。
課題としては2値化しているのでエッジ部分がジャギってしまったり少し汚くなってしまうことです。

■ 追記

しっかりとしたアプローチで実装している記事を見つけたのでリンクを張っておきます。

https://strv.dev/blog/unrealengine--lets-implement-a-single-mesh-renderer/

Discussion