高/標準のダイナミック レンジ ディスプレイで DirectX と高度な色を使用する

このトピックでは、DirectX を高度な色のシナリオ (高ダイナミックレンジ (HDR)、自動システム カラー管理を使用した広色域 (WCG)、高ビット深度など) を使用する方法について説明します。 上記の機能強化の少なくとも 1 つを備えた Premium パーソナル コンピューター (PC) ディスプレイが普及しており、従来の標準ダイナミック レンジ (SDR) ディスプレイよりも大幅に高い色再現性が提供されています。

このトピックでは、Windows Advanced Color サポートの背後にある主要な技術的概念の概要について説明します。 HDR、WCG、および高ビット深度の DirectX コンテンツをこれらのディスプレイのいずれかにレンダリングするための要件と手順について説明します。 カラーマネージド アプリ (ICC プロファイルの使用など) がある場合は、自動色管理によってシナリオの色精度が向上する方法について説明します。

Windows の高度な色の概要

高度な色 は、標準ディスプレイよりも大幅に高い色忠実度を持つディスプレイのオペレーティング システム (OS) テクノロジの傘用語です。 主な拡張機能については、以下のセクションで説明します。 高度なカラー機能は、Windows 10、バージョン 1709 (Fall Creators Update) の HDR ディスプレイ、および Windows 11 バージョン 22H2 (10.0;ビルド 22621) リリース。

高ダイナミックレンジ

ダイナミックレンジとは、シーン内の最大輝度と最小輝度の差を指します。これは多くの場合、ニット (平方センチメートルあたりカンデラ) で測定されます。 この夕焼けのような現実世界のシーンは、多くの場合、輝度の10桁のダイナミックレンジを持っています。人間の目は適応後にさらに大きな範囲を識別することができます。

シーン内の明るさと最も暗い点がラベル付けされた夕焼けの画像

Direct3D 9 以降、グラフィックス エンジンは、このレベルの物理的に正確な忠実性でシーンを内部的にレンダリングすることができました。 ただし、標準的なダイナミック レンジ ディスプレイでは、輝度の大きさが 3 桁を少し超えるだけしか再現できないため、HDR レンダリングされたコンテンツは、ディスプレイの限られた範囲にトーンマップ (圧縮) する必要がありました。 HDR10(BT.2100)標準に準拠するものを含む新しいHDRディスプレイは、この制限を打破します。たとえば、高品質の自己放射ディスプレイは、6桁を超える可能性があります。

広色域

色域とは、ディスプレイが再現できる色合いの範囲と彩度を指します。 人間の目が認識できる最も飽和した自然な色は、レーザーによって生成されるような純粋な単色光で構成されています。 ただし、多くの場合、メインストリーム のコンシューマー ディスプレイでは、人間が認識できる色の約 35% のみを表す sRGB 色域内でのみ色を再現できます。 次の図は、人間の "スペクトル軌跡" またはすべての知覚可能な色 (特定の輝度レベル) を表したものです。小さい三角形は sRGB 色域です。

人間のスペクトル軌跡と sRGB 色域の図

ハイエンドのプロフェッショナル PC ディスプレイは、人間が認識できる色の約半分をカバーする Adobe RGB や DCI-P3 など、sRGB よりも大幅に広い色域を長い間サポートしてきました。 そして、これらの広い色域ディスプレイは、より一般的になってきています。

自動システムカラー管理

色管理は、デバイス間で正確で一貫した色再現を保証するテクノロジとプラクティスです。 デジタル コンテンツ作成者の場合、ビジュアル コンテンツの色 (写真、製品イメージ、ロゴなど) が、対象ユーザーの多様なデジタル デバイスと同じように表示されるようにすることが重要です。

Windows は、イメージ カラー管理 (ICM) 以降の Windows カラー システム (WCS) API を使用して、Windows 2000 以降のカラー管理サポート API を提供してきました。 ただし、これらの API は、色の管理を希望または必要とするアプリのヘルパーにすぎませんでした。ほとんどのアプリとデジタルコンテンツは業界標準のsRGBカラースペースを想定していましたが、OSによって色管理されることはありませんでした。 それは以前は妥当な想定でしたが、高品質の広い色域ディスプレイははるかに一般的になってきています。

Windows の新しいバージョンでは、システムの色の自動管理がサポートされています。を使用すると、すべての Windows アプリのすべての色 (色に対応しているかどうかに関係なく) が、サポートされているすべてのディスプレイに正確かつ一貫して表示されます。

注意

自動色管理は、ディスプレイ ハードウェアのプロパティではありません。代わりに、sRGB よりも色域が大きいディスプレイを適切にサポートする Windows 機能です。

深い精度/ビット深度

数値の精度 (ビット深度) は、色を一意に識別するために使用される情報の量を指します。 ビット深度が高いほど、バンディングなどのアーティファクトなしで非常に似た色を区別できます。 メインストリームPCディスプレイはカラーチャンネルあたり8ビットをサポートし、人間の目は知覚可能な歪みを避けるために少なくとも10〜12ビットの精度を必要とします。

シミュレートされたカラー チャネルあたり 2 ビットとチャネルあたり 8 ビットの風車の画像

高度な色の前に、デスクトップ ウィンドウ マネージャー (DWM) では、ディスプレイでサポートされているビット深度が高い場合でも、カラー チャネルあたりわずか 8 ビットでコンテンツを出力するようにウィンドウ アプリを制限しました。 高度な色を有効にすると、DWM は IEEE 半精度浮動小数点 (FP16) を使用してその構成を実行し、ボトルネックを排除し、ディスプレイの完全な精度を使用できるようにします。

Windows Advanced Color システム アーキテクチャ

このセクションの情報は、Advanced Color アプリをビルドする場合は省略可能です。ただし、アプリのレンダリングと動作を最適化するためにテクノロジがどのように動作するかを理解しておくと役立ちます。

このセクションでは、簡略化された図を使用して、Windows グラフィックス スタックの関連コンポーネントについて説明します。

Windows グラフィックス スタックのブロック図: カーネルを表示する DWM へのアプリ

既存の Windows: 8 ビット/sRGB 表示

何十年もの間、コンシューマー ディスプレイと Windows グラフィックス スタックは、チャネルあたり約 8 ビット (ピクセルあたり 24 ビット) の sRGB コンテンツに基づいていました。 DirectX などのグラフィックス API を使用するアプリでは、高いビット深度と拡張色空間を使用して内部レンダリングを実行できます。ただし、OS では、暗黙的な sRGB とシステムカラー管理を使用しない 8 ビット整数のみがサポートされていました。

SDR ディスプレイ スタックのブロック図: 色管理なしの sRGB、8 ビットに制限

つまり、アプリによってレンダリングされる追加の色データは、表示時に失われます。ディスプレイ上で正確な再現を確保するために、アプリが色管理自体を実行する必要がありました。

Windows 10バージョン 1703: HDR ディスプレイと高度な色

Windows 10、バージョン 1703 では、HDR ディスプレイ用の高度な色機能の最初のバージョンが導入されました。 OS グラフィックス スタックでは、いくつかの大幅な進歩が必要です。

  • HDR ディスプレイ シグナリングのサポート
  • 高ビット深度の標準色空間を使用したシステム構成
  • 自動システムカラー管理

HDR ディスプレイ スタックのブロック図: FP16、scRGB、自動色管理

各進歩については、以下のサブセクションで説明します。 最終的には、拡張アプリの色データが OS によって正しく保持され、HDR ディスプレイで正確に再現されるようになりました。

HDR ディスプレイ シグナリングのサポート

DisplayPort や HDMI などのディスプレイ コネクタを介した HDR シグナリングでは、主にチャネル精度あたり 10 ビット (またはそれ以上) と BT.2100 ST.2084 色空間が使用されます。 ディスプレイ カーネル、ディスプレイ ドライバー、および基になる GPU ハードウェアはすべて、このシグナリング モードの検出、選択、および駆動をサポートする必要があります。

高ビット深度の標準色空間を使用したシステム構成

BT.2100 ST.2084 カラー スペースは、HDR カラーをエンコードするための効率的な標準ですが、多くのレンダリングおよびコンポジション (ブレンド) 操作には適していません。 また、人間が目に見える色の2/3未満をカバーするBT.2100をはるかに超える技術と色空間をサポートするOSを将来実証したいと考えています。 最後に、可能な場合は、電力とパフォーマンスを向上させるために GPU リソースの消費量を最小限に抑えたいと考えています。

HDR モードの場合、デスクトップ ウィンドウ マネージャー (DWM) は、次のように定義された標準コンポジションカラースペース (CCCS) を使用します。

  • scRGB 色空間 (線形ガンマを使用した BT.709/sRGB プライマリ)
  • IEEE 半精度 (FP16 ビット深度)

これにより、上記のすべての目標のバランスが取られます。 CCCS では、[0, 1] の数値範囲外の色値を使用できます。有効なFP16値の範囲を考えると、それは500万ニット以上の輝度値を含む、自然な人間の視覚範囲よりも大きさの多くの色の順序を表すことができます。 FP16 はリニア ガンマ ブレンド操作に対して優れた精度を備えていますが、GPU メモリの消費量と従来の単精度 (FP32) の帯域幅の半分を消費し、品質損失を受け取らなくなります。

自動システムカラー管理

Windows はマルチタスク環境であり、ユーザーはウィンドウが重なって任意の数の SDR アプリと HDR アプリを同時に実行できます。 したがって、すべての種類のコンテンツが正しく、ディスプレイへの出力時に最高の品質で見えるのが重要です。たとえば、BT.2100 ST.2084 (HDR) ビデオ ウィンドウが再生されている sRGB (SDR) 生産性アプリなどです。

HDR モードの場合、Windows は次の 2 つの段階でカラー管理操作を実行します。

  1. DWM は、ブレンドする前に、各アプリをネイティブの色空間から CCCS に変換します。
  2. ディスプレイ カーネルは、OS フレームバッファーを CCCS からワイヤ形式の色空間 (BT.2100 ST.2084) に変換します。

DWM で発生する自動色管理のブロック図と、DWM およびディスプレイ カーネルで発生する自動色管理の表示カーネル ブロック図、パート 2

注意

どちらの段階でも、色管理操作は色空間変換 (マトリックスと 1DLUT) で構成されます。 ディスプレイのターゲット色域を超える色は、数値的にクリップされます。

Windows 11、バージョン 22H2: SDR は高度な色で表示されます

HDRディスプレイの普及は急速に増加していますが、SDRディスプレイは今後も重要なままです。 Windows 10のHDRサポート、バージョン1703は、SDRディスプレイを強化するために必要な基礎の大部分を築きました。 Windows 11、バージョン 22H2 は、高度な色と自動色管理機能を特定の対象となる SDR ディスプレイに拡張します。 Advanced Color SDR ディスプレイのグラフィックス ブロック図は、HDR によく似ています。

SDR AC ディスプレイ スタックのブロック図: FP16、scRGB、自動色管理

ビット深度が高い SDR ディスプレイ シグナリングのサポート

SDR ディスプレイの基になるシグナリングは変更されませんが、Windows 11バージョン 22H2 リリースでは、ディスプレイの機能に応じて、チャネルあたり 10 ビット以上がサポートされます。

高ビット深度の標準色空間を使用したシステム構成

CCCS でのブレンドを含む DWM Advanced Color 機能は、HDR ディスプレイからほとんど変更されません。 メインの違いは、DWM は SDR ディスプレイで表示参照される輝度を使用し、HDR ディスプレイではシーン参照の輝度を使用することです。 これにより、高度な色でレンダリングされたコンテンツが OS によって解釈される方法が変わります。

表示の種類 輝度の動作 1.0f はどのように解釈されるか
SDR 表示参照 ディスプレイの参照白レベルとして
Hdr シーン参照 80 nit (標準参照白) として

自動システムカラー管理

OSシステムのカラー管理機能もHDRディスプレイとほとんど変わりません。 メインの違いは、ディスプレイ カーネルは、HDR ディスプレイ用の標準の BT.2100 ST.2084 色空間ではなく、ディスプレイの測色および調整データによって定義された表示参照色空間に変換される点です。

プロビジョニングが必要な表示

ディスプレイ カーネルの出力カラー管理操作を定義するには、MHC ICC プロファイルからの正確なデータが必要です。 したがって、有効なプロファイルを持つ製造元またはディスプレイ調整プロバイダーによって特別にプロビジョニングされた SDR ディスプレイのみが、自動カラー管理の対象となります。 詳細については、「 高度な色を使用した ICC プロファイルの動作 」を参照してください。

システム要件とオペレーティング システムのサポート

Windows 10、バージョン 1709 は、HDR ディスプレイの高度な色のサポートを最初に出荷しました。 Windows 11バージョン 22H2 リリースでは、正確なプロビジョニング データを持つ SDR ディスプレイの高度な色のサポートが追加されています。

このトピックでは、アプリが HDR ディスプレイのWindows 10バージョン 2004 (以降) と、SDR ディスプレイ用のWindows 11バージョン 22H2 リリース (またはそれ以降) を対象としていることを前提としています。

表示

高ダイナミックレンジディスプレイは、HDR10またはBT.2100 ST.2084標準を実装する必要があります。 HDR ディスプレイの品質は大きく異なる場合があります。 VESA DisplayHDR など、認定されているディスプレイを強くお勧めします。 Windows 11 バージョン 22H2 リリース以降、Windows では、設定アプリに既知の表示の認定状態が表示されます。

標準のダイナミック レンジ ディスプレイには、高度な色をサポートするための正確なカラー プロビジョニング データが必要です。 Windows 11バージョン 22H2 リリースでは、このデータをオーバーライドするためにサポートされている唯一の方法は、MHC ICC プロファイルを使用することです。さらに、ユーザーまたはディスプレイの製造元が自動色管理を有効にしている必要があります。 詳細については、「 高度な色を使用した ICC プロファイルの動作」を参照してください。

グラフィックス プロセッサ (GPU)

SDR ディスプレイと HDR ディスプレイの両方で完全な高度な色機能を使用するには、最新の GPU が必要です。

  • AMD Radeon RX 400 シリーズ (Polaris) 以降
  • NVIDIA GeForce 10 シリーズ (Pascal) 以降
  • 選択された Intel Core 10th Gen (Ice Lake) 以降*

注意

Intel コード名 Comet Lake (5 桁モデル コード) チップセットでは、完全な機能は提供されません。

ハードウェア コーデック アクセラレーション (10 ビット HEVC、10 ビット VP9 など) や PlayReady サポート (SL3000) など、シナリオによっては、追加のハードウェア要件が適用される場合があります。 詳細については、GPU ベンダーにお問い合わせください。

グラフィックス ドライバー (WDDM)

使用可能な最新のグラフィックス ドライバーは、Windows Updateまたは GPU ベンダーまたは PC 製造元の Web サイトから強くお勧めします。 このトピックでは、HDR ディスプレイ用の WDDM 2.7 (Windows 10 バージョン 2004) と、SDR ディスプレイ用の WDDM 3.0 (Windows 11バージョン 21H2) のドライバー機能に依存しています。

サポートされているレンダリング API

Windows 10では、さまざまなレンダリング API とフレームワークがサポートされています。 高度な色のサポートは、基本的に、DXGI または Visual Layer API を使用して最新のプレゼンテーションを実行できるアプリに依存します。

そのため、これらのプレゼンテーション メソッドのいずれかに出力できるレンダリング API では、Advanced Color をサポートできます。 これには、以下のものが含まれます (ただし、これらに限定されません)。

  • Direct3D 11
  • Direct3D 12
  • Direct2D
  • Win2D
    • 下位レベルの CanvasSwapChain または CanvasSwapChainPanel API を使用する必要があります。
  • Windows.UI.Input.Inking
    • DirectX を使用したカスタム ドライ インク レンダリングをサポートします。
  • XAML
    • MediaPlayerElement を使用した HDR ビデオの再生をサポートします。
    • Image 要素を使用した JPEG XR イメージのデコード サポートします。
    • SwapChainPanel を使用した DirectX 相互運用をサポートします。

動的表示機能の処理

Windows 10は、パワー効率の高い統合パネルからハイエンドのゲームモニターやテレビまで、幅広い高度なカラー対応ディスプレイをサポートしています。 Windows ユーザーは、ユビキタスな既存の SDR ディスプレイを含め、アプリがこれらのバリエーションをすべてシームレスに処理することを期待しています。

Windows 10は、HDR と高度な色の機能をユーザーに制御します。 アプリでは、現在のディスプレイの構成を検出し、機能の変更に動的に応答する必要があります。 これは、ユーザーが機能を有効または無効にしたり、異なるディスプレイ間でアプリを移動したり、システムの電源状態が変更されたりするなど、さまざまな理由で発生する可能性があります。

オプション 1: AdvancedColorInfo

注意

AdvancedColorInfo Windows ランタイム API は、レンダリング API とは無関係に使用でき、SDR ディスプレイ用の Advanced Color をサポートし、イベントを使用して機能が変更されたときに通知します。 ただし、ユニバーサル Windows プラットフォーム (UWP) アプリでのみ使用できます。デスクトップ アプリ (CoreWindow を持たない) では使用できません。 詳細については、「Windows ランタイム API はデスクトップ アプリでサポートされていません」を参照してください。

まず、DisplayInformation::GetAdvancedColorInfo から AdvancedColorInfo のインスタンスを取得します。

現在アクティブになっている詳細な色の種類をチェックするには、AdvancedColorInfo::CurrentAdvancedColorKind プロパティを使用します。 これはチェックにとって最も重要なプロパティであり、アクティブな種類に応じてレンダリングパイプラインとプレゼンテーションパイプラインを構成する必要があります。

高度な色の種類 表示機能
SDR 高度な色機能のない SDR 表示
Wcg 高いビット深度と自動色管理を備えた SDR ディスプレイ
Hdr すべての高度な色機能を備えたHDRディスプレイ

サポートされている高度な色の種類をチェックしますが、必ずしもアクティブではない場合は、AdvancedColorInfo::IsAdvancedColorKindAvailable を呼び出します。 たとえば、その情報を使用して、HDR または自動カラー管理を有効にできるように、ユーザーに Windows 設定 アプリへの移動を求めることができます。

AdvancedColorInfo の他のメンバーは、SMPTE ST.2086 静的 HDR メタデータに対応するパネルの物理カラー ボリューム (輝度とクロミナンス) に関する定量的な情報を提供します。 ST.2086はもともとHDRディスプレイ用に設計されていましたが、その情報は役に立ち、HDRとSDRディスプレイの両方で利用できます。 この情報を使用して、アプリのトーン マッピングと色域マッピングを構成する必要があります。

高度な色機能の変更を処理するには、 DisplayInformation::AdvancedColorInfoChanged イベントに 登録します。 このイベントは、何らかの理由でディスプレイの高度な色機能のパラメーターが変更された場合に発生します。

そのイベントを処理するには、 AdvancedColorInfo の新しいインスタンスを取得し、変更された値を確認します。

IDXGIOutput6

注意

DirectX グラフィックス インフラストラクチャ IDXGIOutput6 インターフェイスは、デスクトップかユニバーサル Windows プラットフォーム (UWP) かにかかわらず、DirectX を使用するすべてのアプリで使用できます。 ただし、 IDXGIOutput6では 、自動色管理などの高度な色機能を備えた SDR ディスプレイはサポートされていません。HDR ディスプレイのみを識別できます。

Win32 デスクトップ アプリを作成し、DirectX を使用してレンダリングする場合は、 DXGI_OUTPUT_DESC1 を使用して表示機能を取得します。 IDXGIOutput6::GetDesc1 を使用して、その構造体のインスタンスを取得します。

現在アクティブになっている高度な色の種類をチェックするには、ColorSpace プロパティを使用します。これはDXGI_COLOR_SPACE_TYPE型で、次のいずれかの値を含みます。

DXGI_COLOR_SPACE_TYPE 表示機能
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 高度な色機能のない SDR 表示
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 すべての高度な色機能を備えたHDRディスプレイ

注意

高度な色機能を備えた SDR ディスプレイも 、DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709として報告されます。DXGI では、2 つの型を区別することはできません。

注意

DXGI では、現在サポートされているがアクティブではない高度な色の種類をチェックすることはできません。

DXGI_OUTPUT_DESC1の他のメンバーのほとんどは、SMPTE ST.2086 静的 HDR メタデータに対応するパネルの物理カラー ボリューム (輝度とクロミナンス) に関する定量的な情報を提供します。 ST.2086はもともとHDRディスプレイ用に設計されていましたが、その情報は便利で、HDRとSDRの両方のディスプレイで利用できます。 この情報を使用して、アプリのトーン マッピングと色域マッピングを構成する必要があります。

Win32 デスクトップ アプリには、高度な色機能の変更に対応するためのネイティブ メカニズムがありません。 代わりに、アプリでレンダー ループを使用する場合は、各フレームで IDXGIFactory1::IsCurrent に対してクエリを実行する必要があります。 FALSE が報告された場合は、新しいDXGI_OUTPUT_DESC1を取得し、変更された値をチェックする必要があります。

さらに、Win32 メッセージ ポンプは 、アプリ が異なるディスプレイ間を移動した可能性があることを示すWM_SIZE メッセージを処理する必要があります。

注意

新しい DXGI_OUTPUT_DESC1を取得するには、現在のディスプレイを取得する必要があります。 ただし、 IDXGISwapChain::GetContainingOutput を呼び出さないでください。 これは、 DXGIFactory::IsCurrent が false になると、スワップ チェーンによって古い DXGI 出力が返されるためです。スワップ チェーンを再作成して現在の出力を取得すると、一時的に黒い画面になります。 代わりに、すべての DXGI 出力の境界を列挙し、アプリ ウィンドウの境界との交差が最も大きいものを決定することをお勧めします。

次のコード例は、GitHub のDirect3D 12 HDR サンプル アプリから取得したものです。

// Retrieve the current default adapter.
ComPtr<IDXGIAdapter1> dxgiAdapter;
ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &dxgiAdapter));

// Iterate through the DXGI outputs associated with the DXGI adapter,
// and find the output whose bounds have the greatest overlap with the
// app window (i.e. the output for which the intersection area is the
// greatest).

UINT i = 0;
ComPtr<IDXGIOutput> currentOutput;
ComPtr<IDXGIOutput> bestOutput;
float bestIntersectArea = -1;

while (dxgiAdapter->EnumOutputs(i, &currentOutput) != DXGI_ERROR_NOT_FOUND)
{
    // Get the retangle bounds of the app window
    int ax1 = m_windowBounds.left;
    int ay1 = m_windowBounds.top;
    int ax2 = m_windowBounds.right;
    int ay2 = m_windowBounds.bottom;

    // Get the rectangle bounds of current output
    DXGI_OUTPUT_DESC desc;
    ThrowIfFailed(currentOutput->GetDesc(&desc));
    RECT r = desc.DesktopCoordinates;
    int bx1 = r.left;
    int by1 = r.top;
    int bx2 = r.right;
    int by2 = r.bottom;

    // Compute the intersection
    int intersectArea = ComputeIntersectionArea(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2);
    if (intersectArea > bestIntersectArea)
    {
        bestOutput = currentOutput;
        bestIntersectArea = static_cast<float>(intersectArea);
    }

    i++;
}

// Having determined the output (display) upon which the app is primarily being 
// rendered, retrieve the HDR capabilities of that display by checking the color space.
ComPtr<IDXGIOutput6> output6;
ThrowIfFailed(bestOutput.As(&output6));

DXGI_OUTPUT_DESC1 desc1;
ThrowIfFailed(output6->GetDesc1(&desc1));

DirectX スワップ チェーンの設定

ディスプレイが現在高度な色機能をサポートしていると判断したら、次のようにスワップ チェーンを構成します。

反転プレゼンテーション モデル効果を使用する

CreateSwapChainFor[Hwnd|コンポジション|CoreWindow] メソッドでは、DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL または DXGI_SWAP_EFFECT_FLIP_DISCARD オプションのいずれかを選択して DXGI フリップ モデルを使用する必要があります。これにより、スワップ チェーンは DWM からの高度な色処理とさまざまな全画面表示の最適化に適しています。 詳細については、「 最適なパフォーマンスを得るには、DXGI フリップ モデルを使用する」を参照してください。

方法 1. FP16 ピクセル形式と scRGB 色空間を使用する

Windows 10では、高度な色のピクセル形式と色空間の 2 つのメインの組み合わせがサポートされています。 アプリの特定の要件に基づいて 1 つ選択します。

汎用アプリでは、オプション 1 を使用することをお勧めします。 これは、すべての種類の高度な色の表示、コンテンツ、レンダリング API に対して機能する唯一のオプションです。 スワップ チェーンを作成するときは、DXGI_SWAP_CHAIN_DESC1DXGI_FORMAT_R16G16B16A16_FLOATを指定します。 既定では、浮動小数点ピクセル形式で作成されたスワップ チェーンは、 DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 色空間を使用するかのように扱われます。 これは、DWM で使用されるのと同じピクセル形式と色空間です。

この組み合わせにより、物理的に可能な任意の色を指定し、ブレンドを含む任意の処理を実行する数値範囲と精度が得られます。

ただし、このオプションでは 1 ピクセルあたり 64 ビットが消費され、従来の UINT8 ピクセル形式と比較して GPU 帯域幅とメモリ消費量が 2 倍になります。 さらに、scRGB では、正規化された [0, 1] の範囲外の数値を使用して、sRGB 色域の外側にある色や、80 ニットを超える輝度を表します。 たとえば、scRGB (1.0、1.0、1.0) は、標準の D65 白を 80 ニットでエンコードします。しかし、scRGB(12.5、12.5、12.5)は、はるかに明るい1000ニットで同じD65白をエンコードします。 一部のグラフィックス操作では、正規化された数値範囲が必要であり、操作を変更するか、色の値を再正規化する必要があります。

そのオプションを使用して輝度値を解釈する方法は、SDR と HDR ディスプレイの間で異なります。以下を参照してください。

オプション 2: UINT10/RGB10 ピクセル形式と HDR10/BT.2100 色空間を使用する

オプション 2 は、アプリが次のすべての条件を満たしている場合にのみ使用できるパフォーマンスの最適化です。

  • HDR ディスプレイをターゲットとする
  • Direct3D 12または Direct3D 11 を使用する
  • スワップ チェーンでは、アルファ/透明度を使用したブレンドは必要ありません

アプリがこれらの条件をすべて満たしていない場合は、オプション 1 を使用する必要があります。

ただし、アプリがオプション 2 に該当する場合は、アプリが HDR10 でエンコードされたコンテンツ (ビデオ プレーヤーなど) を使用している場合や、主にゲームなどの全画面表示シナリオで使用される場合は、パフォーマンスが向上する可能性があります。 スワップ チェーンを作成するときは、 DXGI_SWAP_CHAIN_DESC1でDXGI_FORMAT_R10G10B10A2_UNORM を指定することを検討 する必要があります。 既定では、これは sRGB 色空間を使用するものとして扱われます。そのため、 IDXGISwapChain3::SetColorSpace1 を明示的に呼び出し、色空間 DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 (HDR10/BT.2100 とも呼ばれます) として設定する必要があります。

このオプションは、従来の UINT8 SDR ピクセル形式と同じ 32 ビット/ピクセルを使用します。 さらに、特定の GPU では、コンテンツを HDR10 ワイヤ形式に変換するために必要な処理が不要になります。

ディスプレイが SDR モードのときに高度なカラー スワップ チェーンを使用する

ディスプレイがすべての高度な色機能をサポートしていない場合でも、Advanced Color スワップ チェーンを使用できます。 このような場合、デスクトップ ウィンドウ マネージャー (DWM) は、数値クリッピングを実行することで、ディスプレイの機能に合わせてコンテンツをダウンコンバートします。 たとえば、FP16 scRGB スワップ チェーンにレンダリングし、標準ディスプレイをターゲットにした場合、数値範囲 [0, 1] の範囲外のすべてがクリップされます。

このダウンコンバージョン動作は、アプリ ウィンドウが異なる高度な色機能を持つ 2 つ以上のディスプレイにまたがっている場合にも発生します。 AdvancedColorInfoIDXGIOutput6 は、メインディスプレイの特性のみを報告するように抽象化されます (ウィンドウの中央を含むディスプレイとして定義メイン)。

アプリの参照を OS SDR 参照のホワイト レベルに合わせる

注意

リファレンスホワイトはHDRディスプレイにのみ適用されます。SDR Advanced Color ディスプレイの場合(1.0、1.0、1.0)は、ディスプレイが再現できる最大の白色輝度を常に意味します。

多くのシナリオでは、アプリは SDR と HDR の両方のコンテンツをレンダリングする必要があります。たとえば、HDR ビデオや UI に対する字幕やトランスポート コントロールをゲーム シーンにレンダリングする場合などです。 SDR リファレンスホワイト レベルの概念を理解して、SDR コンテンツが HDR ディスプレイで正しく表示されるようにすることが重要です。 [参照白] は、拡散白オブジェクト (用紙のシートや UI など) が HDR シーンに表示される明るさを示します。 HDR カラー値には シーンと呼ばれる明るさがあるため、可能な最大パネル値を基準にせず、特定の色値を絶対輝度レベルで表示する必要があります。 たとえば、scRGB (1.0、1.0、1.0) と HDR10 (497、497、497) はどちらも、80 ニット輝度で D65 白を正確にエンコードします。 Windows では、ユーザーは SDR 参照の白レベル を自分の好みに合わせて調整できます。これは、Windows が sRGB (1.0、1.0、1.0) でレンダリングする輝度です。 デスクトップHDRモニターでは、SDRリファレンスホワイトレベルは通常約200ニットに設定されます。

HDR アプリでは、ユーザーが目的の参照ホワイト レベルを設定するか、システムによって構成された値を読み取れるようにする必要があります。 シーン内の拡散白色の色の値を SDR 参照の白レベルにマップする必要があります。 これには、線形ガンマ空間でアプリ のフレームバッファーを乗算する必要があります。

注意

ラップトップなどの明るさコントロールをサポートするディスプレイでは、Windows は HDR (シーン参照) コンテンツの輝度をユーザーの望ましい明るさレベルに合わせて調整しますが、アプリには見えません。 HDR 信号のビット精度の再現を保証しようとしている場合を除き、一般的に無視できます。

アプリが常に SDR と HDR を個別のサーフェスにレンダリングし、OS の構成に依存している場合、Windows は自動的に正しい調整を実行して SDR コンテンツを目的の白レベルに昇格させます。 たとえば、アプリで XAML を使用し、HDR コンテンツを独自の SwapChainPanel にレンダリングする場合です。

ただし、アプリで SDR と HDR コンテンツの独自の構成を 1 つのサーフェスに実行する場合は、SDR 参照のホワイト レベル調整を自分で実行する必要があります。 そうしないと、一般的なデスクトップ表示条件下で SDR コンテンツが暗すぎる可能性があります。 最初に、現在の SDR 参照ホワイト レベルを取得し、レンダリングする SDR コンテンツの色の値を調整する必要があります。

手順 1. 現在の SDR 参照ホワイト レベルを取得する

現在の SDR 参照ホワイト レベルは、次のいずれかの方法で取得できます。

手順 2. SDR コンテンツの色の値を調整する

Windows では、標準 (既定) の参照白レベルが 80 ニットで定義されています。 したがって、標準の sRGB (1.0、1.0、1.0) を FP16 スワップ チェーンに白でレンダリングすると、80 nits の輝度で再現されます。 実際のユーザー定義参照ホワイト レベルと一致させるには、SDR コンテンツを 80 ニットから AdvancedColorInfo.SdrWhiteLevelInNits で指定されたレベルに調整する必要があります。

FP16 と scRGB、または線形 (1.0) ガンマを使用する色空間を使用してレンダリングする場合は、単に SDR の色値に を AdvancedColorInfo.SdrWhiteLevelInNits / 80掛けることができます。 Direct2D を使用している場合は、定義済みの定数 D2D1_SCENE_REFERRED_SDR_WHITE_LEVELがあり、値は 80 です。

D2D1_VECTOR_4F inputColor; // Input SDR color value.
D2D1_VECTOR_4F outputColor; // Output color adjusted for SDR white level.
auto acInfo = ...; // Obtain an AdvancedColorInfo.

float sdrAdjust = acInfo->SdrWhiteLevelInNits / D2D1_SCENE_REFERRED_SDR_WHITE_LEVEL;

// Normally in DirectX, color values are manipulated in shaders on GPU textures.
// This example performs scaling on a CPU color value.
outputColor.r = inputColor.r * sdrAdjust; // Assumes linear gamma color values.
outputColor.g = inputColor.g * sdrAdjust;
outputColor.b = inputColor.b * sdrAdjust;
outputColor.a = inputColor.a;

HDR10 などの非線形ガンマ色空間を使用してレンダリングする場合は、SDR ホワイト レベルの調整を実行する方が複雑になります。 独自のピクセル シェーダーを作成する場合は、線形ガンマに変換して調整を適用することを検討してください。

トーン マッピングを使用して HDR コンテンツをディスプレイの機能に適応させる

HDR と Advanced Color のディスプレイは、その機能の点で大きく異なります。 たとえば、最小および最大の輝度と色域では、再現が可能です。 多くの場合、HDR コンテンツにはディスプレイの機能を超える色が含まれます。 最高の画質を得るために、HDR トーン マッピングを実行することが重要です。基本的には、コンテンツの視覚的意図を維持しながら、ディスプレイに合わせて色の範囲を圧縮します。

適応する最も重要な 1 つのパラメーターは、MaxCLL (コンテンツ ライト レベル) とも呼ばれる最大輝度です。より洗練されたトーンマッパーは、最小輝度(MinCLL)やカラープライマリーも適応します。

手順 1. ディスプレイのカラー ボリューム機能を取得する

ユニバーサル Windows プラットフォーム (UWP) アプリ

AdvancedColorInfo を使用して、ディスプレイのカラー ボリュームを取得します。

Win32 (デスクトップ) DirectX アプリ

DXGI_OUTPUT_DESC1を使用して、ディスプレイのカラー ボリュームを取得します。

手順 2. コンテンツのカラー ボリューム情報を取得する

HDR コンテンツの由来に応じて、その輝度と色域情報を判断する方法は複数あります。 特定の HDR ビデオファイルと画像ファイルには、SMPTE ST.2086 メタデータが含まれています。 コンテンツが動的にレンダリングされた場合は、内部レンダリング ステージ (シーン内で最も明るい光源など) からシーン情報を抽出できる場合があります。

より一般的だが計算コストの高いソリューションは、レンダリングされたフレームでヒストグラムやその他の分析パスを実行することです。 GitHub の Direct2D 高度なカラー イメージ レンダリング サンプル アプリ は、Direct2D を使用してこれを行う方法を示しています。最も関連性の高いコード スニペットを以下に示します。

// Perform histogram pipeline setup; this should occur as part of image resource creation.
// Histogram results in no visual output but is used to calculate HDR metadata for the image.
void D2DAdvancedColorImagesRenderer::CreateHistogramResources()
{
    auto context = m_deviceResources->GetD2DDeviceContext();

    // We need to preprocess the image data before running the histogram.
    // 1. Spatial downscale to reduce the amount of processing needed.
    DX::ThrowIfFailed(
        context->CreateEffect(CLSID_D2D1Scale, &m_histogramPrescale)
        );

    DX::ThrowIfFailed(
        m_histogramPrescale->SetValue(D2D1_SCALE_PROP_SCALE, D2D1::Vector2F(0.5f, 0.5f))
        );

    // The right place to compute HDR metadata is after color management to the
    // image's native colorspace but before any tonemapping or adjustments for the display.
    m_histogramPrescale->SetInputEffect(0, m_colorManagementEffect.Get());

    // 2. Convert scRGB data into luminance (nits).
    // 3. Normalize color values. Histogram operates on [0-1] numeric range,
    //    while FP16 can go up to 65504 (5+ million nits).
    // Both steps are performed in the same color matrix.
    ComPtr<ID2D1Effect> histogramMatrix;
    DX::ThrowIfFailed(
        context->CreateEffect(CLSID_D2D1ColorMatrix, &histogramMatrix)
        );

    histogramMatrix->SetInputEffect(0, m_histogramPrescale.Get());

    float scale = sc_histMaxNits / sc_nominalRefWhite;

    D2D1_MATRIX_5X4_F rgbtoYnorm = D2D1::Matrix5x4F(
        0.2126f / scale, 0, 0, 0,
        0.7152f / scale, 0, 0, 0,
        0.0722f / scale, 0, 0, 0,
        0              , 0, 0, 1,
        0              , 0, 0, 0);
    // 1st column: [R] output, contains normalized Y (CIEXYZ).
    // 2nd column: [G] output, unused.
    // 3rd column: [B] output, unused.
    // 4th column: [A] output, alpha passthrough.
    // We explicitly calculate Y; this deviates from the CEA 861.3 definition of MaxCLL
    // which approximates luminance with max(R, G, B).

    DX::ThrowIfFailed(histogramMatrix->SetValue(D2D1_COLORMATRIX_PROP_COLOR_MATRIX, rgbtoYnorm));

    // 4. Apply a gamma to allocate more histogram bins to lower luminance levels.
    ComPtr<ID2D1Effect> histogramGamma;
    DX::ThrowIfFailed(
        context->CreateEffect(CLSID_D2D1GammaTransfer, &histogramGamma)
        );

    histogramGamma->SetInputEffect(0, histogramMatrix.Get());

    // Gamma function offers an acceptable tradeoff between simplicity and efficient bin allocation.
    // A more sophisticated pipeline would use a more perceptually linear function than gamma.
    DX::ThrowIfFailed(histogramGamma->SetValue(D2D1_GAMMATRANSFER_PROP_RED_EXPONENT, sc_histGamma));
    // All other channels are passthrough.
    DX::ThrowIfFailed(histogramGamma->SetValue(D2D1_GAMMATRANSFER_PROP_GREEN_DISABLE, TRUE));
    DX::ThrowIfFailed(histogramGamma->SetValue(D2D1_GAMMATRANSFER_PROP_BLUE_DISABLE, TRUE));
    DX::ThrowIfFailed(histogramGamma->SetValue(D2D1_GAMMATRANSFER_PROP_ALPHA_DISABLE, TRUE));

    // 5. Finally, the histogram itself.
    HRESULT hr = context->CreateEffect(CLSID_D2D1Histogram, &m_histogramEffect);
    
    if (hr == D2DERR_INSUFFICIENT_DEVICE_CAPABILITIES)
    {
        // The GPU doesn't support compute shaders and we can't run histogram on it.
        m_isComputeSupported = false;
    }
    else
    {
        DX::ThrowIfFailed(hr);
        m_isComputeSupported = true;

        DX::ThrowIfFailed(m_histogramEffect->SetValue(D2D1_HISTOGRAM_PROP_NUM_BINS, sc_histNumBins));

        m_histogramEffect->SetInputEffect(0, histogramGamma.Get());
    }
}

// Uses a histogram to compute a modified version of MaxCLL (ST.2086 max content light level).
// Performs Begin/EndDraw on the D2D context.
void D2DAdvancedColorImagesRenderer::ComputeHdrMetadata()
{
    // Initialize with a sentinel value.
    m_maxCLL = -1.0f;

    // MaxCLL is not meaningful for SDR or WCG images.
    if ((!m_isComputeSupported) ||
        (m_imageInfo.imageKind != AdvancedColorKind::HighDynamicRange))
    {
        return;
    }

    // MaxCLL is nominally calculated for the single brightest pixel in a frame.
    // But we take a slightly more conservative definition that takes the 99.99th percentile
    // to account for extreme outliers in the image.
    float maxCLLPercent = 0.9999f;

    auto ctx = m_deviceResources->GetD2DDeviceContext();

    ctx->BeginDraw();

    ctx->DrawImage(m_histogramEffect.Get());

    // We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
    // is lost. It will be handled during the next call to Present.
    HRESULT hr = ctx->EndDraw();
    if (hr != D2DERR_RECREATE_TARGET)
    {
        DX::ThrowIfFailed(hr);
    }

    float *histogramData = new float[sc_histNumBins];
    DX::ThrowIfFailed(
        m_histogramEffect->GetValue(D2D1_HISTOGRAM_PROP_HISTOGRAM_OUTPUT,
            reinterpret_cast<BYTE*>(histogramData),
            sc_histNumBins * sizeof(float)
            )
        );

    unsigned int maxCLLbin = 0;
    float runningSum = 0.0f; // Cumulative sum of values in histogram is 1.0.
    for (int i = sc_histNumBins - 1; i >= 0; i--)
    {
        runningSum += histogramData[i];
        maxCLLbin = i;

        if (runningSum >= 1.0f - maxCLLPercent)
        {
            break;
        }
    }

    float binNorm = static_cast<float>(maxCLLbin) / static_cast<float>(sc_histNumBins);
    m_maxCLL = powf(binNorm, 1 / sc_histGamma) * sc_histMaxNits;

    // Some drivers have a bug where histogram will always return 0. Treat this as unknown.
    m_maxCLL = (m_maxCLL == 0.0f) ? -1.0f : m_maxCLL;
}

手順 3. HDR トーンマッピング操作を実行する

トーンマッピングは本質的に損失の多いプロセスであり、多くの知覚的または客観的なメトリックに最適化できるため、単一の標準アルゴリズムはありません。 Windows では、Direct2D の一部として、および Media Foundation HDR ビデオ再生パイプラインに組み込みの HDR トーンマッパー効果 が提供されます。 その他の一般的に使用されるアルゴリズムとしては、ACES Filmic、Reinhard、ITU-R BT.2390-3 EETF (電気電気伝達関数) などがあります。

この次のコード例では、簡略化されたラインハード トーンマッパー演算子を示します。

// This example uses C++. A typical DirectX implementation would port this to HLSL.
D2D1_VECTOR_4F simpleReinhardTonemapper(
    float inputMax, // Content's maximum luminance in scRGB values, e.g. 1.0 = 80 nits.
    float outputMax, // Display's maximum luminance in scRGB values, e.g. 1.0 = 80 nits.
    D2D1_VECTOR_4F input // scRGB color.
)
{
    D2D1_VECTOR_4F output = input;

    // Vanilla Reinhard normalizes color values to [0, 1].
    // This modification scales to the luminance range of the display.
    output.r /= inputMax;
    output.g /= inputMax;
    output.b /= inputMax;

    output.r = output.r / (1 + output.r);
    output.g = output.g / (1 + output.g);
    output.b = output.b / (1 + output.b);

    output.r *= outputMax;
    output.g *= outputMax;
    output.b *= outputMax;

    return output;
}

HDR および WCG 画面コンテンツのキャプチャ

Windows.Graphics.Capture 名前空間のピクセル形式や IDXGIOutput5::D uplicateOutput1 メソッドなどのピクセル形式の指定をサポートする API は、ピクセル情報を失うことなく HDR および WCG コンテンツをキャプチャする機能を提供します。 コンテンツ フレームを取得した後は、追加の処理が必要であることに注意してください。 たとえば、HDR から SDR へのトーン マッピング (インターネット共有用の SDR スクリーンショット コピーなど) や、適切な形式 (JPEG XR など) を使用したコンテンツの保存などです。

従来のカラー管理と ICC プロファイルの動作の変更

高度な色管理と自動色管理により、すべてのアプリ、レガシ、モダンの一貫性と比色精度の高い表示色が保証されます。 ただし、一部のアプリでは、International Color Consortium (ICC) カラー プロファイルを使用して独自の明示的なカラー管理を実行できます。

SDR ディスプレイまたは HDR ディスプレイで Advanced Color がアクティブになっている場合、ディスプレイ ICC プロファイルの動作は、下位互換性のない方法で変化します。 アプリがディスプレイ ICC プロファイルで動作する場合、Windows には互換性ヘルパーが用意され、アプリが引き続き正しい動作を得られるようにします。

ICC プロファイルの動作の変更と、高度な色との互換性を最大限に高めるためにアプリを適応させる方法の詳細については、「高度な色を使用した ICC プロファイルの動作」を参照してください。

その他のリソース