OpenColorIO ( OCIO ) でHDR出力する
OCIOを使用し、様々な条件の下でHDR出力やSDR出力を行ってみました。
この記事はOCIOを使用していないUE標準のWindows HDR出力が成功していることを前提としています。
OCIO
説明のために、OCIOレンダリングパスのシェーダーのことをOCIOシェーダー、OCIOシェーダーの中の.ocioファイルによる変換処理のことをOCIO変換と、ここでは定義します。
HDR - Windows HDR オン
WindowsでHDRコンテンツを確認する場合、Windows HDR オンにして、 r.HDR.EnableHDROutput 1 にします。
Windows視点ではエディター全体がHDRコンテンツとして動作しています。
この条件の時だけ、パッケージとエディターで動作が異なります。
パッケージ
OCIOシェーダーのレンダーターゲットフォーマットはPF_A2B10G10R10になります。
OCIOシェーダーからRec.2100 PQで出力する必要があるので、OCIO変換でRec.2100 PQを出力し、それをそのままOCIOシェーダーで出力すれば良いです。
エディター
OCIOシェーダーのレンダーターゲットフォーマットはPF_FloatRGBAになります。
OCIOシェーダーからScRGBで出力する必要があるのですが、OCIO変換でScRGBを出力とする方法を見つけることが出来ず、またOCIOシェーダーの出力をScRGBとして出力する方法も用意されていないようです。
なのでOCIOプラグイン側を改造して、OCIOシェーダーでOCIO変換の後にRec.2100 PQをScRGBに変換すると上手くいきました。
OCIO変換での出力はRec.2100 PQとしておけば、パッケージ時はそのまま出力し、エディター時はRec.2100 PQをScRGBに変換すると良いので実装しやすいと思います。
改造内容ですが、WindowsHDRの場合View.Family->RenderTarget->GetDisplayOutputFormat()でHDR_ACES_1000nit_ScRGBなどが取得できるのでそれに応じてシェーダー対応を行えば良いです。
SDR - Windows HDR オン
Windows HDR オンの状態のHDRモニターでSDR出力を確認するための設定になります。
Windows HDR オンにして、 r.HDR.EnableHDROutput 0 にします。
この場合Windows視点ではエディター全体がSDRコンテンツとして動作しています。
OCIOシェーダーのレンダーターゲットフォーマットはPF_A2B10G10R10になります。
OCIOシェーダーからsRGBで出力する必要があるので、OCIO変換でsRGBを出力し、それをそのままOCIOシェーダーで出力すれば良いです。
HDR - Windows HDR オフ
Windows HDRはオフで、モニターの設定をRec.2100 PQのHDRプレビューにした場合です。
基本的には使用しないと思います。
r.HDR.EnableHDROutputは動作せず無関係です。
OCIOシェーダーのレンダーターゲットフォーマットはPF_A2B10G10R10になります。
OCIOシェーダーからRec.2100 PQで出力する必要があるので、OCIO変換でRec.2100 PQを出力し、それをそのままOCIOシェーダーで出力すれば良いです。
ただ、最終出力は色は合ってそうですがマッハバンドが確認できるので処理の何処かで低精度のフォーマットになっているようです。
SDR - Windows HDR オフ
Windows HDRはオフで、モニターの設定はsRGBです。
通常のSDRの確認になると思います。
r.HDR.EnableHDROutputは動作せず無関係です。
OCIOシェーダーのレンダーターゲットフォーマットはPF_A2B10G10R10になります。
OCIOシェーダーからsRGBで出力する必要があるので、OCIO変換でsRGBを出力し、それをそのままOCIOシェーダーで出力すれば良いです。
補足
OCIOのプラグイン改造の枠を超えてしまうのですが、WindowsEditorでもパッケージと同様にScRGBを使わずにRec.2100 PQで出力する改造を行うという方法もあります。
試した感じだとChooseHDRDeviceAndColorGamutとFD3D12DynamicRHI::Initの2箇所のWITH_EDITORを実行しないようにすると上手くいきました。