ぼっちプログラマのメモ

UE4とかVRとかについて書いたり書かなかったり。

UMG(Widget)をテクスチャ(RenderTarget)に描画する方法について (サンプル配布)

*はじめに
UMGの描画内容をテクスチャに焼き込みたいケースはしばしばあります。3Dモデルの表面に反映させたり、以前説明したStereoLayerに使用したり…その他色々!

f:id:pafuhana1213:20170521162948p:plain


SceneCapture2Dを使うことで簡単に実現はできるのですが、処理負荷の問題やレベルのどこかに配置する必要があったりと面倒です。ということで、今回はUMGの内容を直接テクスチャに描画する方法を紹介します。

説明とかいいから使いたいんだけど!?という方は、↓のサンプルプロジェクトをどうぞ。プラグイン化してます。4.15で作りました。
github.com

実装方法

WidgetRendererを使って、Widgetの内容をWindowではなくTextureに描画します。
FWidgetRenderer | Unreal Engine API Reference (うーん、あまり説明載ってない…)

WidgetRendererはBP側には公開されていないため、C++で機能実装しBPノード化する必要があります。サンプルプロジェクトのプラグインを見たほうが早い気もしますが、念のためブログにもC++コードを載せときます。

C++コード

h

 #include "UMG.h"
 #include "SlateBasics.h"
 #include "SlateCore.h"
 #include "SWidget.h"
 #include "WidgetRenderer.h"
  
 ...
 
 UFUNCTION(Category = "UMG", BlueprintCallable)
 static void DrawWidgetToTarget(UTextureRenderTarget2D * Target, UUserWidget * WidgetToRender, FVector2D DrawSize, bool UseGamma, TextureFilter Filter, float DeltaTime );

cpp

void UXXXLibrary::DrawWidgetToTarget(UTextureRenderTarget2D * Target, UUserWidget * WidgetToRender, FVector2D DrawSize, bool UseGamma, TextureFilter Filter, float DeltaTime)
{
	if (!WidgetToRender)
	{
		return;
	}
	if (DrawSize == FVector2D(0, 0))
	{
		return;
	}
	if (!Target)
	{
		return;
	}

	FWidgetRenderer * r = new FWidgetRenderer(UseGamma);
	TSharedRef<SWidget> ref = WidgetToRender->TakeWidget();
	r->DrawWidget(Target, ref, DrawSize, DeltaTime);

	delete r;
}

その他

Build.csのPublicDependencyModuleNames.AddRangeに "UMG" "Slate", "SlateCore" を追加

最後に

これで以下のようにノードを組むことで、
f:id:pafuhana1213:20170521171024p:plain
UMGの内容をテクスチャに描画できます。
f:id:pafuhana1213:20170521170917p:plain

毎フレームテクスチャに描画すると処理負荷が気になってくるので、UMG側で変更が発生した時だけ書き込む仕組みにすることをおすすめします。あとは、今回のコードは最低限度レベルのものなので、是非色々と拡張してみて下さい!

おわり!