toruのブログ

月1くらいで記事書きたい。

OBS を改造して Windows上の HDR対応ゲームの輝度を確認可能にした (False Color表示)

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表示の詳細は筆者の過去記事を参照して頂きたい。

trev16.hatenablog.com

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 はバックアップを取っておくこと

drive.google.com

  • ② OBS の Advance設定の SDR White Level100 nits に設定する (図1)

図1. Advance設定の SDR White Level の設定

4.2. キャプチャ画面への False Color表示の適用

以下の 2点を実施する。

  • ① 輝度を確認したいアプリケーションを OBS でキャプチャする *1
  • ② フィルタから "HDR Tone Mapping (Override)" を選び SDR White Level100 nits に設定する *2 (図2)

図2. 改造した HDR Tone Mapping (Override) の設定

4.3. 動作確認

以下のテスト動画に対して "HDR Tone Mapping (Override)" フィルタを適用して図3 のようになれば正常に動作している。


テスト動画

図3. テスト動画に False Color表示を適用した例

ただし、筆者が保証できる動画再生環境は 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点が分かった。

  1. "HDR Tone Mapping (Override)" の実処理は hdr_tonemap_filter.effect ファイル内に記述されている
  2. .effect ファイルは起動時に OBS が読み込むため事前のコンパイルが不要である

そのため "HDR Tone Mapping (Override)" の改造を行う方針とした。

OBS の内部処理

OBS のフィルタ処理で False Color表示を実現するにあたり、改めて OBS 内部の色処理について確認を行った。デバッガを使い調査した結果を図4に示す。

図4. False Color表示を含めた色処理の概要図

図の補足説明をしておく。まず明確にしておきたいのは、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 REBIRTHMonster Hunter WildsSky: 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 に示す。

github.com

主要な変更箇所は以下の 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 への変換が行われた