ガンマ補正の使用

ガンマ補正 (略してガンマ) は、画像内のピクセル値をコード化してデコードするためにシステムが使用する非線形演算の名前です。

ガンマとは何であり、何のためのものですか?

グラフィックス パイプラインの最後に、イメージがコンピューターから出てモニター ケーブルに沿って移動する場所に、ピクセル値をその場で変換できるハードウェアの小さな部分があります。 このハードウェアは通常、ルックアップ テーブルを使用してピクセルを変換します。 このハードウェアでは、表示されるサーフェスから取得した赤、緑、青の値を使用して、表内のガンマ補正値を検索し、実際のサーフェス値ではなく、修正された値をモニターに送信します。 したがって、この参照テーブルは、任意の色を他の色に置き換える機会です。 テーブルにはそのレベルのパワーが含まれていますが、一般的な使用方法は、モニターの応答の違いを補正するために画像を微妙に調整することです。 モニターの応答は、ピクセルの赤、緑、青の成分の数値を、そのピクセルの表示された明るさに関連付ける関数です。

これがこの表の目的でしたが、ゲーム開発者は、心理的効果のために画面全体を赤く点滅させるなど、クリエイティブな用途を見つけました。 最新のゲーム アプリでは、各フレームの後処理の一環として、通常、このようなことを行うための他の方法を提供します。 実際には、ガンマ テーブルはモニターの応答を調整するために使用されている可能性があるため、そのままにしておくことをお勧めします。ガンマ ランプに対する卸売の変更によって、この慎重な調整が破棄されます。

ガンマ補正を決定する科学は複雑であり、ここでは「ガンマ」という名前がどこから来たかを照らす以外には提示されません。 CRT (つまり、昔ながらのガラス) モニターの応答は複雑な関数ですが、これらのモニターの物理学は、この電力関数で粗く表すことができる応答を示すという意味です。

brightness( input ) = inputgamma

ガンマ値は通常、値 2.0 に近い値です。 LCDモニターとその他のすべての新しい技術は、同様の反応を示すために特別に設計されているため、すべてのソフトウェアと画像をこれらの新しい技術のために再調整する必要はありません。 sRGB 標準では、このガンマ値が正確に 2.2 であることを宣言しており、この値は広く実装されている標準となっています。

人間の目には、CRT パワー関数をほぼ反転させる応答関数もあります。 つまり、ピクセルの認識される明るさは、そのピクセルの RGB 値とほぼ直線的に上がります。

ガンマ値 2.2 は事実上の標準になっているため、通常、この表でエンコードされたガンマ曲線についてあまり心配する必要がなく、線形の 1 対 1 のマッピングとして残すことができます。 適切な色のマッチングは、もちろん、この関数で絶妙な注意を払う必要がありますが、その議論は、このトピックの範囲を超えています。 Windows には、ユーザーがディスプレイをガンマ 2.2 に調整できるツールが含まれています。このツールでは、ルックアップ テーブル ハードウェアを使用して、コンピューター用に慎重に選択された微妙な調整を導き出します。 ユーザーは、"色の調整" を検索して、このツールを実行できます。 また、このプロセスを自動化する特定のモニター用に明確に定義されたカラー プロファイルもあります。 "色の調整" ツールは、これらの新しいモニターを検出し、調整が既に行われていることをユーザーに通知できます。

色の値に電力法則をエンコードするこの概念は、特にテクスチャのグラフィックス パイプラインの他の場所でも役立ちます。 テクスチャの場合は、先ほど話した対数人間の目の反応のために、暗い色をより正確にしたいと考えています。 パイプラインのこの部分でのガンマの慎重な処理が重要です。 詳細については、「 色空間のデータの変換」を参照してください。

このトピックの残りの部分では、フレーム バッファー データとモニターの間のパイプラインのこの最後の部分でのガンマ補正にのみ焦点を当てています。 調整ウィザードを作成する場合、または後処理手順が実用的でない全画面表示アプリで特殊効果を作成する場合は、次に必要な情報を示します。

Windows でのガンマの背景

Windows コンピューターには通常、バイトのトリプレットを受け取り、バイトのトリプレットを出力する参照テーブルであるガンマ テーブルがあります。 これらのトリプレットは、768 (256 x 3) バイトの RAM です。 これは、表示形式に RGB BYTE 値のトリプレットが含まれているが、表示形式の範囲が [0,1] より大きい場合 (浮動小数点値など) に必要な変換を記述するのに十分な表現力がない場合に問題ありません。 ガンマを制御する Windows の API は、表示形式が複雑化するにつれて進化しています。

ガンマ制御を提供する最初の Windows API は、Windows グラフィックス デバイス インターフェイス (GDI) の SetDeviceGammaRampGetDeviceGammaRamp です。 これらの API は、256 エントリの 3 つの WORD 配列で動作し、各 WORD エンコードは 0 から 1 まで、WORD 値 0 と 65535 で表されます。 通常、WORD の余分な精度は、実際のハードウェア参照テーブルでは使用できませんが、これらの API は柔軟性を備えることを意図していました。 これらの API は、このセクションで後述する他の API とは異なり、ID 関数からのわずかな逸脱のみを許可します。 実際、ランプ内のすべてのエントリは、ID 値の 32768 以内である必要があります。 この制限は、アプリがディスプレイを完全に黒にしたり、他の読み取り不可能な色にしたりすることはできません。

次の API は、SetDeviceGammaRamp と同じパターンとデータ形式に従う Microsoft Direct3D 9 の SetGammaRamp です。 Direct3D 9 ガンマ ランプの既定値は特に役に立ちません。API が 0 から 65535 の観点で定義されている場合でも、0 から 65535 ではなく、0 から 255 に初期化された WORD のランプです。

最新の API は IDXGIOutput::SetGammaControl です。 この API には、DXGI の増加した表示形式のセット (チャネルあたり 10 個の整数ビット、16 ビット浮動小数点形式、XR_BIAS拡張範囲形式など) に適合するため、ガンマ制御を表現するためのより柔軟なスキームがあります。

これらの API はすべて同じハードウェアで動作し、同じ値を変更します。 Direct3D 9 および DXGI API は "書き込み専用" です。 ハードウェアの値を読み取って変更し、設定することはできません。 ランプのみを設定できます。 さらに、アプリが全画面表示の場合にのみガンマを設定できます。 この制限は、デスクトップが常に読み取り可能であることを保証するもう 1 つの方法です。 つまり、アプリは独自の表示を妨げる可能性がありますが、アプリが全画面表示になったときに (たとえば、alt-tab または ctrl-alt-del を使用して) 前のガンマ ランプが復元されます。

ディスプレイ ハードウェアの進化

一部の新しいモニターでは、さまざまな強度を表示できます。 ただし、表示形式で 0 から 1 までの値のみを表すことができる場合、ディスプレイは 0 を最も暗い値に、1 を最も明るい値にマップする必要があります。 この最も明るい値は、白い背景に黒いテキストを含む Web ページを快適に表示するには明るすぎるかもしれませんが、湖から光る日光や空をフォークする雷を見るなど、明るすぎる特殊効果には最適です。 そのため、これらのより広い範囲を表現する方法が必要です。 DXGI 1.1 以降には、1.0 が快適な白い値を表す表示形式の値が含まれており、明るい特殊効果の表示形式の値が広くなります。 DXGI 1.1 では、これらのより広い値を表すことができる 2 つの表示形式 (DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM と 16 ビット浮動小数点) がサポートされています。 これらの形式の詳細については、「 拡張形式の詳細」を参照してください。 次に、DXGI の IDXGIOutput::SetGammaControl ガンマ API に 1.0 より大きいピクセル値が必要な理由について説明します。

DXGI のガンマ制御機能

DXGI を使用すると、ディスプレイ ドライバーはガンマ コントロールをステップごとの線形関数として表現できます。 このステップごとの線形関数は、この関数の制御ポイント、関数が変換できる値の範囲、および変換後に適用できる追加のオプションのスケールとオフセット操作によって定義されます。 アプリは IDXGIOutput::GetGammaControlCapabilities メソッドを呼び出して、 DXGI_GAMMA_CONTROL_CAPABILITIES 構造内のすべてのコントロール機能を取得できます。

このグラフは、4 つのコントロール ポイントのみを持つ線形関数を示しています。

ガンマ補正線形関数

DXGI は、コントロール ポイントをサーフェスの色軸に沿った位置で定義します。 上のグラフでは、コントロール ポイントの位置は 0、0.5、0.75、1.0 です。 これらのコントロール ポイントは、ハードウェアが 0 ~ 1.0 の範囲の値を変換できることを示します。 DXGI は、DXGI_GAMMA_CONTROL_CAPABILITIESControlPointPositions 配列メンバーにこれらのコントロール ポイントを一覧表示し、常に順番に宣言します。 DXGI は ControlPointPositions 配列の最初の要素のみを入力し、DXGI_GAMMA_CONTROL_CAPABILITIESの NumGammaControlPoints メンバーを持つ要素の数 示します。 NumGammaControlPoints が 1025 未満の場合、DXGI は ControlPointPositions 要素の残りの部分を未定義のままにします。

このグラフで表されるハードウェアは、値を 0 から 1.25 の範囲に変換できます。 そのため、DXGI は MinConvertedValue メンバーと MaxConvertedValue メンバーをそれぞれ 0.0f と 1.25f に設定します。

DXGI は、DXGI_GAMMA_CONTROL_CAPABILITIESScaleAndOffsetSupported メンバーを設定して、ハードウェアがスケールとオフセットの機能をサポートしているかどうかを示します。 ハードウェアでスケールとオフセットがサポートされている場合は、単純な 1 対 1 の参照テーブルを保持しますが、出力を [0,1] より大きい範囲に拡大するようにテーブルの出力を調整します。 ハードウェアは、最初に参照テーブルから出てくる値をスケーリングしてから、それらをオフセットします。

Note

同じコンピューターに接続されているモニターによって、ガンマ制御機能が異なる場合があります。 さらに、ガンマ制御機能は、実際には出力の表示モードに応じて変化する可能性があります。 そのため、アプリが全画面表示モードに入った後は、常に IDXGIOutput::GetGammaControlCapabilities を呼び出してガンマ制御機能のクエリを実行することをお勧めします。

 

これらのガンマ制御機能の値を使用して、 IDXGIOutput::SetGammaControl API を使用して設定できる制御値を派生させることができます。

DXGI を使用したガンマコントロールの設定

ガンマ コントロールを設定するには、IDXGIOutput::SetGammaControl API を呼び出すときに、DXGI_GAMMA_CONTROL構造体へのポインターを渡します。

DXGI_GAMMA_CONTROLScale メンバーと Offset メンバーを設定して、ハードウェアが参照テーブルから取得する値に適用するスケールとオフセットの値を指定します。 スケールとオフセットの機能を使用しない場合、またはハードウェアにその機能がない場合は、スケールを 1 に設定し、オフセットを 0 に設定しても問題ありません (つまり、1 ずつのスケールは影響を受けず、ゼロのオフセットは影響を受けません)。

DXGI_GAMMA_CONTROLGammaCurve 配列メンバーを、ガンマ曲線上のポイントのDXGI_RGB構造体の一覧に設定します。 各 DXGI_RGB 要素は、そのポイントの赤、緑、青のコンポーネントを表す float 値を指定します。 ガンマ曲線ではアルファ値は使用されません。 DXGI_GAMMA_CONTROL_CAPABILITIESの NumGammaControlPoints から取得した 数値を使用 して、 GammaCurve 配列内の要素の数を入力します。 GammaCurve 配列に配置する各要素は、各コントロール ポイントの高さです。

上のグラフでは、各コントロール ポイントの垂直方向の配置を制御できるようになり、赤、緑、青に対して個別のコントロールが用意されていることに注目してください。 たとえば、緑と青の値をすべて 0 に設定し、赤の値を 0 から 1 の昇順の階段に設定できます。 このシナリオでは、表示される画像には赤の部分のみが表示され、青と緑は黒で表示されます。 また、すべての色に対して降りる階段を設定して、反転表示を行うこともできます。 GammaCurve 配列に配置する値は、DXGI_GAMMA_CONTROL_CAPABILITIESMinConvertedValue メンバーと MaxConvertedValue メンバーから取得した値内に含まれている必要があります。

ガンマコントロールの実用性

DXGI のガンマ コントロールは、アプリが全画面表示の場合にのみ適用されます。 Windows は、アプリが終了するか、ウィンドウ モードに戻ったときに、以前の状態の表示を復元します。 ただし、アプリが全画面表示モードに再び入った場合、Windows はアプリのガンマ状態を復元しません。 アプリは、全画面表示モードに再び入るときに、ガンマ状態を明示的に復元する必要があります。

すべてのアダプターがガンマ制御をサポートしているわけではありません。 アダプターがガンマ制御をサポートしていない場合、ガンマ ランプを設定する呼び出しは無視されます。

リモート デスクトップで実行されるアプリは、ガンマをまったく制御できません。

マウス カーソルがハードウェアに実装されている場合 (ほとんどの場合)、通常はガンマ設定に応答しません。

DXGI のプログラミング ガイド