0. 更新履歴
日付 | 内容 |
---|---|
2025/05/20 | 記事公開。 |
2025/06/22 | OBS でフィルタを有効化した状態で録画 or 配信を行うと画面が緑がかる問題を修正。 4.1. に添付してある zip の hdr_tonemap_filter.effect を更新。 |
1. 背景
- 筆者はこれまで Windows 環境で HDR対応ゲームの輝度を確認しづらいと感じていた
- ゲームの 1 シーンの輝度を調べるにしても数分の時間を必要としていた
- 非常に効率が悪かったので別の仕組みを作ることにした
2. 目的
- OBS を利用して HDR対応ゲームの輝度を簡単に確認する仕組みを作る
- 具体的には OBS のキャプチャ画面に False Color表示を適用することで、色で輝度を確認可能にする
3. 結論
OBS に標準搭載されている "HDR Tone Mapping (Override)" フィルタを改造して False Color 表示を実装し、色で輝度値を判断可能とした。Final Fantasy VII Rebirth のプレイに適用した様子を以下に示す。
![]() |
|
---|---|
デモ動画 | 輝度と色の関係 |
なお、OBS のフィルタ実装は真面目にやると面倒な点が多かったので、今回は 標準搭載の "HDR Tone Mapping (Override)" フィルタを改造 して実現した。
使用している False Color表示の詳細は筆者の過去記事を参照して頂きたい。
4. 使い方
OBS で False Color表示を適用をするための手順を以下に示す。"HDR Tone Mapping (Override)" フィルタ処理を行うファイル置き換えと、OBS のパラメータ設定が必要となる。
4.1. 事前準備
事前に以下の 2点を実施しておく。
- ① 添付の zip ファイルに含まれる hdr_tonemap_filter.effect を "C:\Program Files\obs-studio\data\obs-plugins\obs-filters\hdr_tonemap_filter.effect" に上書き保存する
- 元の hdr_tonemap_filter.effect はバックアップを取っておくこと
- ② OBS の Advance設定の SDR White Level を 100 nits に設定する (図1)
4.2. キャプチャ画面への False Color表示の適用
以下の 2点を実施する。
- ① 輝度を確認したいアプリケーションを OBS でキャプチャする *1
- ② フィルタから "HDR Tone Mapping (Override)" を選び SDR White Level を 100 nits に設定する *2 (図2)
4.3. 動作確認
以下のテスト動画に対して "HDR Tone Mapping (Override)" フィルタを適用して図3 のようになれば正常に動作している。
テスト動画
ただし、筆者が保証できる動画再生環境は Windows 11 24H2 (26100.4061) 上の Google Chrome (Version 136.0.7103.114) or Microsoft Edge (Version 136.0.3240.76) だけである。それ以外の環境での動作は保証できない *3。
注意事項
- 筆者が改造した hdr_tonemap_filter.effect はオリジナル版が GPL-2.0 license なので、改造版も同じく GPL-2.0 license となる
- 本フィルターの利用によって生じた いかなる損害・トラブルについても、作者は一切責任を負わないものとする。あらかじめご了承願いたい
- また、今回の False Color表示は以下のバージョンで確認した。その他のバージョンで正常動作するかは申し訳ないが保証できない
項目 | バージョン |
---|---|
OS | Windows 11 24H2, Build 26100.4061 |
GPU | RTX 5070 Ti, Version 576.26 (GRD) |
OBS | Version 31.0.3 |
技術的な説明
以下で技術的な説明を行っていく。なお、以後の話は全て Windows 11 で HDR表示を有効にした前提となる。
"HDR Tone Mapping (Override)" を改造する方針とした理由
簡単にまとめると「色々と面倒だった」からなのだが、もう少し詳しく理由を書いておく。
筆者は当初、obs-shaderfilter というプラグインの .shader ファイルとして False Color表示を実装予定だった。しかし obs-shaderfilter v2.4.3 では1.0 を超える RGB値がクリップされてしまい、正しく処理を適用できなかった。そこでソースコードを解析しつつ obs-shaderfilter 本体の改造を検討したところ、むしろ OBS 本体のコードを修正する方が実装が簡単 であることが分かった。
しかし、C言語のソースコードに手を加えると、OBS本体のアップデートごとに改造版の再ビルドが必要となり運用が面倒くさい。そこで更に調査を進めたところ "HDR Tone Mapping (Override)" について以下の2点が分かった。
- "HDR Tone Mapping (Override)" の実処理は hdr_tonemap_filter.effect ファイル内に記述されている
- .effect ファイルは起動時に OBS が読み込むため事前のコンパイルが不要である
そのため "HDR Tone Mapping (Override)" の改造を行う方針とした。
OBS の内部処理
OBS のフィルタ処理で False Color表示を実現するにあたり、改めて OBS 内部の色処理について確認を行った。デバッガを使い調査した結果を図4に示す。
図の補足説明をしておく。まず明確にしておきたいのは、OBS のフィルタ処理は Canvas の色空間 であるGS_CS_709_EXTENDED
で行われる、という点である。
GS_CS_709_EXTENDED
は (R, G, B) = (1.0, 1.0, 1.0) が 100 nits として扱われる色空間であり*4、(R, G, B) = (1.0, 1.0, 1.0) が 80 nits として扱われる Windows の scRGBとは輝度値の扱いが異なる。
そのため、OBS では前処理としてGS_CS_709_EXTENDED
への変換を行う。基本的には Windows の DWM で使われる scRGB からの変換となるのだが、Game Capture の場合は動作が異なる。Game Capture の場合は Windows の DWM を経由せずに映像を取得するため、ゲームの色空間から直接GS_CS_709_EXTENDED
に変換が行われる。デバッガで FINAL FANTASY VII REBIRTH、Monster Hunter Wilds、Sky: Children of the Light の 3ゲームについて調べたところGS_R10G10B10A2
からGS_CS_709_EXTENDED
への変換が行われていることを確認した *5。
OBS のエフェクト (.effect ファイル) について
今回、hdr_tonemap_filter.effect というファイルを改造したため、.effect ファイルについても簡単に説明しておく。
.effect ファイルは文字通り OBSのエフェクト処理を記述するためのファイルである。構文としては HLSL に極めて近いものが使用されており、頂点シェーダーとピクセルシェーダーを記述できる[3][4]。
また、.effect ファイルはフィルタの適用時に読み込まれる仕組みのため、C言語のソースと異なり事前のコンパイルが不要である。例として hdr_tonemap_filter.effect が読み込まれる箇所の ソースコード を以下に示す。
static void *hdr_tonemap_filter_create(obs_data_t *settings, obs_source_t *context) { struct hdr_tonemap_filter_data *filter = bzalloc(sizeof(*filter)); char *effect_path = obs_module_file("hdr_tonemap_filter.effect"); // <-- パスの指定 filter->context = context; obs_enter_graphics(); filter->effect = gs_effect_create_from_file(effect_path, NULL); // <-- hdr_tonemap_filter.effect の読み込み obs_leave_graphics(); bfree(effect_path); // (中略) obs_source_update(context, settings); return filter; }
hdr_tonemap_filter.effect の改造箇所について
hdr_tonemap_filter.effect に対して筆者が適用した差分を以下の diff に示す。
主要な変更箇所は以下の PSReinhard関数の変更である。
float4 PSReinhard(FragData f_in) : TARGET { float4 rgba = image.Sample(textureSampler, f_in.uv); rgba.rgb *= multiplier; rgba.rgb = rec709_to_rec2020(rgba.rgb); - rgba.rgb = reinhard(rgba.rgb); + rgba.rgb = apply_false_color_y(rgba.rgb); rgba.rgb = rec2020_to_rec709(rgba.rgb); return rgba; }
このすることで通常のトーンマッピング処理を False Color表示に差し替えた。なお apply_false_color_y の処理は 筆者の Python実装 を Copilot先生に HLSL翻訳してもらうことで実現した。
感想
今回の作業で OBS に対する理解度がグッと高まったのを感じた。やはりデバッガを使って色々と試すのは大事だと思った。
これで Windows上のあらゆる HDRコンテンツをリアルタイムに簡単に解析できるようになった。ゲームコンテンツだけでなく、その他の HDRコンテンツ(例えば静止画の Gain Map表示など)についても解析を行い、理解を深めていきたい。
参考資料
[1] OBS Studio’s documentation, "enum gs_color_space - Core Graphics API", https://docs.obsproject.com/reference-libobs-graphics-graphics#c.gs_color_space
[2] Microsoft Learn, "Use DirectX with Advanced Color on high/standard dynamic range displays", https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range
[3] OBS Studio’s documentation, "Effects (Shaders)", https://docs.obsproject.com/reference-libobs-graphics-effects
[4] OBS Studio’s documentation, "Rendering Graphics", https://docs.obsproject.com/graphics
*1:Windows Capture / Display Capture / Game Capture のどれでも可
*2:Advance設定に加えてフィルタ設定でも SDR White Level を 100 nits にする必要がある
*3:保証したいのは山々なのだが、ブラウザ側のHDR表示仕様がいつ変わるかは筆者にも分からないのである。少なくとも昨年の今頃とはブラウザの表示仕様は変わっているorz
*4:ただし、100 nits になるのは Advance設定の SDR White Level を 100 nits に設定した場合に限る
*5:余談だが、自作のHDRソフト使ってバッファを FP16 に設定したところ GS_RGBA16F から GS_CS_709_EXTENDED への変換が行われた