【UE5】Unity Tonemapper Neutral & ACES – Unreal Engine 5.3

Unreal Engine

水ノ茉の宣伝

準備中...
ゲームを作る予定なの
水ノ茉こおり

作業環境

  • Windows 10
  • Unreal Engine 5.3
  • Unity 2021.3.37f1
    • Core RP Library 12.1.14
    • Universal RP 12.1.14
  • Visual Studio 2022 (17.8.3)
  • Visual Studio Code
  • RenderDoc v1.32

始まり

この記事の続きだったりします。

続きっぽくない記事名だって?
半角英字を横に並べたい気分だったのよさ。

さて、熱が冷めないうちにNeutralとACESを移植したいと思います。

筆者さんは🔥熱しやすくて🧊冷めやすい性格なのです。

怠い性格ですが利点として気分が乗った時の瞬間火力💥💥は常人よりも高いです。
というか高くないとマジで使いモノにならない性格なので、高いと思い込むようにしています。

冷めると鈍足デバフ💤を自分で掛けちゃう困ったさんでもありますが。

作業内容と微塵も関係ない導入はこの程度にして始めるとしますか。
(絵文字楽しい。)

トーンマッパ(Tonemapper)について

HDRとLDRが分かるとすんなり理解できる説明文だと思います。

Tone Mapping (トーン マッピング) 機能の目的は、広範囲の HDR (ハイダイナミック レンジ) カラーを局所的な LDR (ローダイナミック レンジ) にマップすることによって、モニターでカラー表示を可能にすることです。

カラー グレーディングとフィルム トーンマッパ

Unity URP

Tonemapping | Universal RP | 12.1.16

Unreal Engine

Just a moment...

UnityとUnreal Engineの差分の纏め

幾つか差分があるので軽く纏めておきます。

BasePassのRenderTargetのFormat

UnityUnreal Engine
R11G11B10_FLOATR16G16B16A16_FLOAT

BasePassのRenderTargetのFormatが異なるためビット誤差が生まれる。

Emissiveピンに接続する直前でfloat精度からr11g11b10精度に変換することで誤差を潰せる。

// NOTE: Include File Paths > '/Engine/Private/PackUnpack.ush'
return UnpackR11G11B10F(PackR11G11B10F(Color));

おそらくBC圧縮結果が異なる

前回差分が無いって書いたけど、BC圧縮の場合は違った。

なんか差分あったんだけど、現状は潰し方が分からなかった。

RGBA8やFLOATなどの圧縮を選べば互換性を確保できる。

sRGB変換するならRGBA8が無難かな。

ACESで使用するD60_2_D65_CAT行列の精度が異なる

Unityの方が軽量・高速化の兼ね合いか知らんですが、精度が低いです。
極力Unityに合わせたかったので、意図的に精度落としています。

UnityUnreal Engine

TonePassのRenderTargetのFormat

UnityUnreal Engine
TonemapR8G8B8A8_SRGBR10G10B10A2_UNORM
GUI View (Editor)R16G16B16A16_TYPELSSR10G10B10A2_UNORM

TonemapPassだけならパックとアンパックでなんとか互換性を保てたかもしれないのですが、GUIに貼り付ける際に更にフォーマットが異なっていたので、もう諦めました。

リポジトリ

最新バージョンのみ保守しています。
過去バージョンが動かないと言われても基本的には知らんがなスタイルです。

実装

前回の実装から変更を加える形です。

Engine/Source/Runtime/Engine/Classes/Engine/Scene.h

Noneの他にNeutralとACESも選択可能にしないといけないので列挙体に変更しました。

githubで実装を見る(L145-L153)

列挙体に変更してあげるとリストボックスで選べるようになります。

githubで実装を見る(L1192)
githubで実装を見る(L2252-L2253)

Engine/Source/Runtime/Engine/Private/Scene.cpp

初期値を修正しておきます。
サボっても暗黙的な変換でなんとかなるはずですが、警告文は基本的に全部潰すべきなので、やめましょうね。
今回は変数名諸共変えているのでダメなんですけどね。

githubで実装を見る(L652)

Engine/Source/Runtime/Engine/Private/SceneView.cpp

気分で変数名を変えたので変えておきます。
Scene.hファイルを編集すると無慈悲な約2,000程度のエンジンビルドを強要されるので、ついでに編集するタイミングとしては良きです。

githubで実装を見る(L1764)

Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessTonemap.cpp

FTonemapperUnityDimからFTonemapperUnityTonemapDimに名称変更です。

githubで実装を見る(L92)
githubで実装を見る(L103)
githubで実装を見る(L119)

FTonemapperUnityTonemapDimを立てる条件をDisable以外が選択された場合に変更します。

githubで実装を見る(L161)

プリプロセッサで分岐しようとしたのですが組み合わせの数が許容値を超過してしまったので、Unityのトーンマップ挙動のオン/オフだけ用意して、残りは動的分岐にしています。ちょっとパフォーマンス悪いので、実際に使用するモードが定まっているのであれば、その部分だけ使って後はコメントアウトするのがいいでしょう。

githubで実装を見る(L367)
githubで実装を見る(L902-L903)

Engine/Shaders/Private/PostProcessTonemap.usf

UnityのTonemapで使用している関数たちです。
ACESで使用する関数や行列は概ねACES.ushで用意されているので、精度差分があるものや記述の仕方が

githubで実装を見る(L90-L240)

コメントアウトからディレクティブに変えました。
やっぱりこのスタイルが好きです。

githubで実装を見る(L643-L645)

ここはコメントアウトじゃないとダメなんだよね。
コンパイラが大混乱して終端が見つからねぇ!!!って激怒しやがる。

githubで実装を見る(L692)

これは元々あった終端(#endif)ですね。

githubで実装を見る(L731)

ここは#elseから#ifに変えました。気分です。

githubで実装を見る(L734)

UnityのTonemap関数を適用する場所ですね。

githubで実装を見る(L736)

おわり!!!

ColorGradingLUTが違うからこれも移植したいな。
てかトーンマッパーの本命ってこれだよね。

移植したい欲だけはあるのですが、NeutralとACESを移植する過程でBC圧縮差分という個人的に結構面白い部分を触れて、だいぶ満たされちゃったので、暫く触ることはないでしょう。

ということで、一旦区切りです。

次からは、また別のことしますわ。

雑談

ネタのストックがバカほどあるのに対して、安定したアウトプットが出来るのは休日の2日間しかないので、永遠と消費が追い付かない件について。

ま、尽きない欲というのは楽しいのですわ。

貪欲に生きましょ。

ポイント失効

500円セール1本分のポイントが失効したようです。

えぇ。メールを見返したら警告が届いていました。

然しながらですよ、平日にメール送られてもねぇ。

仕事してるんですわ。

こんなの休日に纏めてチェックしたり、流し見で『ほへぇ』ぐらいでしょう。

――凹む。

振り返ると筆者の買い方も悪かったんですよね。

定期的にポチポチ買っていたので、失効期限がまちまちなのですよ。

約3,000ぐらい溜まっているので纏めて消費するのがいいでしょうかね。

サマーセールも開催中だし、タイミングも良いでしょう。

てか次が2024/7/10 23:59:59に失効するという割と近況。

みんなも気を付けてね。

この商品は既に購入済みです。

筆者さんフィーリングに従って購入したい派なので、中身をあんまり見ないでバスケットに入れるをポチッっとしているのですが――

一覧表示のGUIがゴミ過ぎて、購入済みに衝突することが度々あります。

絞り込みに購入済みタイトル非表示とか実装して欲しいです。

てかあるのかな。

調べたことないから知らんだけかな。

オトメきのオープニング映像をパロりたい件について

当然見たことありますよね。

筆者はようつべプレ垢なので、オフラインに最高画質で保存しております。

マジで逸れるけどさ、YouTubeのオフライン再生、あれカウント入れてくれねぇかな。あとループ再生も。

1分38秒 > 98秒、1時間 > 3,600秒、1時間ループ再生したら36回カウントされるわけですよ。

んで3時間ぐらい聴いてたら108回。

勿体ない。。。

話を戻しまして――

初めて見た時からなのですが Unreal Engine で再現したい欲がヤバいのです。

今年はゲームプレイ再開を機に、封印していた趣味たちを少しずつ解放しようと意気込んでいるですよ。

つまり?

それに従って再現しないとですね!!!

ただねぇ。どうやって記事に起こそうか迷い中なの。

実装するコンテンツは全年齢なんだけど、元ネタが年齢制限じゃん。

取り扱いが微妙過ぎるのよね。

ま、あくまで、ここで上げてるコンテンツは筆者のアーカイブに過ぎないので、やりたいことやるだけですけど。

つまりはそういうことだね。

若干の懸念点は好きなこと過ぎて、拘りが発動して暫く公開が滞る可能性を秘めている点ですね。

本能に従って楽しく作りますわ。