Constrain Aspect Ratio指定時のDrawDebug~系の表示がずれる

この質問は、以下のスレッドに関連して作成されました: [Constrain Aspect [Content removed]

お世話になっております。

表題の件の内容について、関連するスレッドとして既に同様の質問がありますが、こちらで提示された解決方法が適切とは思えず改めてご質問させてください。

解決方法としてはUGameplayStatics::ProjectWorldToScreenをパッチする方法が上げられていましたが、こちらの関数は5.7.1現在Costrain Aspect Ratioの内容を反映するようになっているように見受けられます。

また、そもそもDrawDebug* 系の描画は座標を3Dで持ったままで​2Dの座標系に変換してる様子はありません。

以前の事例からも、シェーダーなどでの座標変換に変更が必要なように見えますがいかがでしょうか。​

再現手順

お世話になっております。

ご指摘について再度ケースを立てて頂きありがとうございます。本件まず DebugDrawSphere の Depth Priority を World -> Foreground に変更しておくと正しい位置に表示することが可能である、という回避策を共有しておきたいと思います。これについては、World だと シーンの深度バッファ(UpscaledSceneDepth)と深度テストを行うため、投影行列とViewRectの不一致が座標変換に影響し位置のずれが発生します。Foregroundだと専用の深度バッファを使用し深度テストを常に通過するため、投影行列の不一致の影響を受けにくいです。ただし、根本的な問題(投影行列とViewRectの不一致)は残っています。

根本的な修正について、DebugView->GetShaderParameters()が返すFViewUniformShaderParametersのTranslatedWorldToClip行列を使用していますが、bConstrainAspectRatioが有効な場合、この行列はConstrainedViewRectに基づいて計算されていますが、OutputViewport.RectがUnscaledViewRectを使用していることで不一致が発生していました。CreateCompositePrimitiveViewでViewRectを変更し、ViewMatricesを再初期化することで FViewUniformShaderParametersが正しく更新され、Worldでも正しく表示されるはずです。ただしウィンドウの最大化等を行うとまだズレがあるので、追加での変更が必要なように思います。取り急ぎお知らせいたします。

static FDebugPrimitivesDrawingContext InitializeDebugPrimitiveTextures(
	FRDGBuilder& GraphBuilder, 
	const FViewInfo& View,
	const FCompositePrimitiveInputs& Inputs,
	const FScreenPassRenderTarget& Output)
{
	// Setup view
	// Use View.ViewRect instead of Output.ViewRect to match the projection matrix.
	// When bConstrainAspectRatio is enabled, View.ViewRect corresponds to ConstrainedViewRect,
	// which is what the projection matrix was calculated based on.
	// Output.ViewRect may use UnscaledViewRect, which would cause a mismatch.
// 修正前:
//	const FIntRect ViewRect = Output.ViewRect;
// 修正後:
	const FIntRect ViewRect = View.ViewRect;
static bool DrawDebugPDE(
	FRDGBuilder& GraphBuilder,
	FDebugPrimitivesDrawingContext& Context,
	const FScreenPassTextureViewport& OutputViewport)
{
	if (!Context.DebugView->DebugSimpleElementCollector.HasAnyPrimitives())
	{
		return false;
	}
 
// 修正前:
//	なし
// 修正後:
	const FIntRect DebugViewRect = Context.DebugView->ViewRect;
 
	// Draw SDPG_World elements, depth tested with SceneColor
	if (Context.DebugView->DebugSimpleElementCollector.HasPrimitives(SDPG_World))
	{
		FDebugPrimitivesPassParameters* PassParameters = GraphBuilder.AllocParameters<FDebugPrimitivesPassParameters>();
		PassParameters->View = Context.DebugView->GetShaderParameters();
		PassParameters->RenderTargets[0] = FRenderTargetBinding(Context.SceneColor.Texture, ERenderTargetLoadAction::ELoad);
		PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(Context.UpscaledSceneDepth, ERenderTargetLoadAction::ELoad, ERenderTargetLoadAction::ELoad, FExclusiveDepthStencil::DepthWrite_StencilWrite);
 
		GraphBuilder.AddPass(
			RDG_EVENT_NAME("DrawDebugPrimitives(SDPG_World)"),
			PassParameters,
			ERDGPassFlags::Raster,
// 修正前:
//			[PassParameters, DebugView=Context.DebugView, OutputViewport](FRDGAsyncTask, FRHICommandList& RHICmdList)
// 修正後:
			[PassParameters, DebugView=Context.DebugView, DebugViewRect](FRDGAsyncTask, FRHICommandList& RHICmdList)
		{
// 修正前:
//			RHICmdList.SetViewport(OutputViewport.Rect.Min.X, OutputViewport.Rect.Min.Y, 0.0f, OutputViewport.Rect.Max.X, OutputViewport.Rect.Max.Y, 1.0f);
// 修正後:
			RHICmdList.SetViewport(DebugViewRect.Min.X, DebugViewRect.Min.Y, 0.0f, DebugViewRect.Max.X, DebugViewRect.Max.Y, 1.0f);

ご確認頂きありがとうございます。本件は UE-361551 としてデータベースに登録し、追加での修正を検討したいと思います。

ご報告頂きありがとうございました。

ありがとうございます。

修正を適用して動作を確認、取り急ぎ当面弊社で主に使うシーンでは問題がなくなったように思います。

ありがとうございます。

引き続き最大化時等の調査よろしくお願いします。