Unreal Engine 5

[UE5]SceneDepthの背景の値はおそらく100,000,000(ただしUE5.8以降は変わりそう)

Unreal Engineのレンダリング結果で物体があるところと背景(何も無いところ)とを区別したいことはそれなりにあるかと思います。直感的にはSceneTextureのOpacityかなと思うわけですが、これは通常は全て0で、Subsurface materialsに対してのみ値が代入されるようです(参考:Opacity mask always blacks)。ただ、遥か昔、確かUnreal Engine 4.10あたりまでは物体が存在する部分は1、背景は0で、いわゆる一般的なOpacity Maskだった記憶があり(参考:SceneTexture: Opacity is broken in 4.8)どこかのタイミングで仕様が変更されたのだと思います。

そのため現在では背景とそれ以外とを区別したい場合にはCustom Stencilを割り当てることが一般的ではないかと思うのですが、Custom Stencilは物体同士の前後関係を見るなどの別の用途に使いたい、というような状況も多いのではないかと思います。

そこで生成AIさんに聞くと、WorldNormalが(0, 0, 0)のところを使うと良いというような回答が返ってきますが、Best Answerではないような気がします。

次に考えるのはSceneDepthで十分に遠いところを背景と見なすことかと思いますが、SceneDepthで物体が何も無いところにはどの値が入っているのでしょうか?生成AIに聞いても「Far Clip Planeの値を使え」など、完全に明後日な回答しか返ってきません(Unreal Engineでは(おそらく…)Far Clip Planeの概念が無い)。

なので、Material ExpressionのDebugノードで調べてみました。

画面左上に物体が来ないようにした上で、上図のように(0, 0)のところに入っている値をDebugScalrValuesノードを用いて確認してみると…

意味不未明な値が返ってきました…。MaximumNumberOfDigitsを増やしてみても同じ数値しか表示されません。これは…桁あふれ???
…ではFloatの2進数表記を直接調べて見ると良い…のかな??と思い、今度はDebugBinaryValues-Floatノードに繋いでみました。ただ、このResultはDebugScalarValuesとは異なりFloat3のようで、下図のようにMakeFloat4ノードを挟んでからでないと接続できませんでした。

結果はこうなりました。

Floatのバイナリ値っぽいものが出てきました。float値の表現方法はたぶんIEEE 754…のはず、と予想し、IEEE-754 Floating Point Converterで変換してみると…

Binary Representation: 01001100101111101011110000100000
Decimal Representation: 100000000
Value actually stored in float: 100000000

ということで、100,000,000が入っているっぽい?確認してみましょう。下図のようにSceneDepthが100,000,000以上か以下かで色分けしてみます。

結果はこうなりました。

出来ている!ただ、これだけでは本当に100,000,000なのかはわかりません。そこでIfノードのBの値を、100,000,000の次に大きな最も小さい値100,000,008.0(100,000,001などはノード上で100,000,000に丸め込まれてしまいました)にすると画面が真っ赤になりました。
DebugScalrValuesノード内のMaterial Expressionsを適切に修正すれば最初から正しい値が出そうですが、複雑で追えていません…。

どれだけ検索しても、生成AIに聞いても100,000,000という値は見つけられなかったのですが、”SceneDepth 100000000″などで検索するといくつか出てきました(参考:Custom Depth Value Outputs?)。

中でも気になるのはCustom depth and large scenesというフォーラムスレッドでのEpicGamesのエンジニアの方の回答で、SceneView.cppのCreateInvDeviceZToWorldZTransform()でこの100,000,000が定義されているようなのですが、これがPixelDepthの計算方法と異なっていることにより、大きなスケールのシーンでPixelDepthとSceneDepth (CustomDepth)とを用いた計算が破綻してしまうことがあるようです。

で、スレッドで紹介されているリンク先が切れていますが、正しくはおそらくこのUE-335270 Custom Depth range is different than Pixel Depth rangeで、どうやらUnreal Engine 5.8ではこの仕様が修正されるようです。

…ので、SceneDepthで何も無い部分の値が100,000,000なのはUnreal Engine 5.7までのようで、5.8以降の値は改めて確認する必要がありそうです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です