Direct2D を使用して効果をレンダリングするアプリケーションでは、数値精度に関して望ましいレベルの品質と予測可能性を実現するように注意する必要があります。 このトピックでは、次の場合に役立つ Direct2D のベスト プラクティスと関連する設定について説明します。
- 効果グラフは、高い数値精度または [0, 1] 範囲外の色に依存しており、常に使用可能であることを確認する必要があります
- または、効果グラフはレンダリングの実装に依存して中間色を [0, 1] 範囲にクランプし、このクランプが常に行われるようにする必要があります
Direct2D は、多くの場合、エフェクト グラフをセクションに分割し、各セクションを個別の手順でレンダリングします。 一部のステップの出力は、既定では数値範囲と精度が制限されている中間 Direct3D テクスチャに格納される場合があります。 Direct2D では、これらの中間テクスチャが使用されるかどうか、またはどこで使用されるかは保証されません。 この動作は、GPU の機能と Windows のバージョンによって異なる場合があります。
Windows 10 では、Direct2D ではシェーダー リンクを使用するため、中間テクスチャの使用が少なくなります。 そのため、Direct2D では、以前の Windows リリースと既定の設定で異なる結果が生成される場合があります。 これは主に、エフェクト グラフでシェーダー リンクが可能であり、そのグラフに拡張範囲の出力色を生成する効果も含まれているシナリオに影響します。
エフェクトレンダリングと中間処理の概要
効果グラフをレンダリングするために、Direct2D はまず "変換" の基になるグラフを見つけます。ここで、変換とは効果内で使用されるグラフ ノードのことです。 Direct2D で使用する Direct3D シェーダーを提供するものなど、さまざまな種類の変換があります。
たとえば、Direct2D は次のようにエフェクト グラフをレンダリングできます。
Direct2D は、エフェクト グラフのレンダリングに使用される中間テクスチャの数を減らす機会を探します。このロジックはアプリケーションに対して不透明です。 たとえば、次のグラフは、Direct3D 描画呼び出しを 1 回使用して Direct2D でレンダリングでき、中間テクスチャは使用できません。
Windows 10 より前では、同じエフェクト グラフ内で複数のピクセル シェーダーが使用されていた場合、Direct2D は常に中間テクスチャを使用していました。 色の値 (明るさや彩度など) を調整するだけのほとんどの組み込み効果は、ピクセル シェーダーを使用して調整します。
Windows 10 では、Direct2D ではこのような場合に中間テクスチャの使用を回避できるようになりました。 これは、隣接するピクセル シェーダーを内部的にリンクすることによって行います。 例えば次が挙げられます。
グラフ内のすべての隣接するピクセル シェーダーがリンクされるわけではないため、Windows 10 では特定のグラフのみが異なる出力を生成します。 詳しい情報は「エフェクトシェーダーリンク」をご参照ください。 主な制限事項は次のとおりです。
- 効果は、最初の効果が複数の効果への入力として接続されている場合、その出力を消費する効果とリンクされません。
- 最初のエフェクトが出力とは異なる論理位置で入力をサンプリングする場合、効果は入力として効果セットとリンクされません。 たとえば、カラー マトリックス効果は入力とリンクされている可能性がありますが、畳み込み効果はリンクされません。
組み込み効果の挙動
多くの組み込み効果では、入力色がその範囲内にある場合でも、未乗算色空間の [0, 1] 範囲外の色が生成される場合があります。 この場合、このような色は数値クリッピングの対象になる可能性があります。 組み込みの効果は通常、事前乗算空間で色を生成する場合でも、未乗算領域の色範囲を考慮することが重要であることに注意してください。 これにより、他の効果が後に色をアンプリマルチプライした場合でも、色が範囲内に収まるようにします。
これらの範囲外の色を出力する可能性がある効果の一部は、"ClampOutput" プロパティを提供します。 これには以下が含まれます:
これらの効果に対して ClampOutput プロパティを TRUE に設定すると、シェーダー リンクなどの要因に関係なく一貫した結果が得られます。 クランプは未乗算空間で発生することに注意してください。
その他の組み込み効果では、その色のピクセル (および "Color" プロパティがある場合) がその範囲内にある場合でも、未乗算領域の [0, 1] 範囲を超える出力色が生成される場合があります。 これには以下が含まれます:
- 変換とスケーリングの効果 (補間モードプロパティがキュービックまたは高品質キュービックの場合)
- 照明効果
- エッジ検出 (オーバーレイ エッジ プロパティが TRUE の場合)
- 接触
- 複合 (Mode プロパティが Plus の場合)
- 温度と濃淡
- セピア
- 彩度
効果グラフ内での数値クリッピングの強制
ClampOutput プロパティを持たない上記の効果を使用する場合、アプリケーションでは数値クランプの強制を検討する必要があります。 これを行うには、ピクセルをクランプする追加の効果をグラフに挿入します。 Color Matrix 効果を使用して、"ClampOutput" プロパティを TRUE に設定し、'ColorMatrix' プロパティを既定値 (パススルー) 値のままにすることができます。
一貫した結果を得る 2 つ目のオプションは、Direct2D により高い精度を持つ中間テクスチャを使用するように要求することです。 これについては以下で説明します。
中間テクスチャの精度の制御
Direct2D には、グラフの精度を制御するいくつかの方法が用意されています。 Direct2D で高精度フォーマットを使用する前に、アプリケーションが GPU で十分にサポートされていることを確認する必要があります。 これを確認するには、 ID2D1DeviceContext::IsBufferPrecisionSupported を使用します。
アプリケーションでは、WARP (ソフトウェア エミュレーション) を使用して Direct3D デバイスを作成し、デバイス上の実際の GPU ハードウェアに関係なく、すべてのバッファー精度がサポートされることを保証できます。 これは、ディスクへの保存中に写真に効果を適用するなどのシナリオで推奨されます。 Direct2D が GPU で高精度バッファー形式をサポートしている場合でも、機能レベル 9.X GPU では、一部の低電力モバイル GPU でのシェーダー演算とサンプリングの精度が制限されているため、このシナリオでは WARP を使用することをお勧めします。
以下のいずれの場合も、要求された精度は実際には Direct2D が使用する最小精度です。 中間が不要な場合は、より高い精度を使用できます。 Direct2D では、同じグラフのさまざまな部分または異なるグラフの中間テクスチャを完全に共有することもできます。 この場合、Direct2D は、関係するすべての操作に対して可能な限り最高の精度を使用します。
ID2D1DeviceContext::SetRenderingControls からの精度の選択
Direct2D の中間テクスチャの精度を制御する最も簡単な方法は、 ID2D1DeviceContext::SetRenderingControls を使用することです。 これにより、エフェクトや変換に対して精度が手動で設定されない限り、すべての中間テクスチャの精度が制御されます。
if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
// Get the current rendering controls
D2D1_RENDERING_CONTROLS renderingControls = {};
Context->GetRenderingControls(&renderingControls);
// Switch the precision within the rendering controls and set it
renderingControls.bufferPrecision = D2D1_BUFFER_PRECISION_32BPC_FLOAT;
Context->SetRenderingControls(&renderingControls);
}
入力とレンダーターゲットの中からの厳密な選択
また、アプリケーションは、エフェクト グラフへの入力の精度に依存して、中間テクスチャの精度を制御することもできます。 これは、ID2D1DeviceContext::SetRenderingControlsを使用してバッファーの精度が指定されておらず、またはエフェクトおよび変換に対して手動で直接設定されていない限り有効です。
効果に対する入力の精度はグラフを介して伝達され、下流の中間の精度が選択されます。 エフェクト グラフ内の異なる分岐が満たされている場合は、入力の最大精度が使用されます。
Direct2D ビットマップに基づいて選択された精度は、そのピクセル形式から決定されます。 ID2D1ImageSource に対して選択された精度は、ID2D1ImageSource の作成に使用される基になる IWICBitmapSource の WIC ピクセル形式から決定されます。 Direct2D では、Direct2D と GPU がサポートしていない精度を使用して、WIC ソースからイメージ ソースを作成することはできません。
Direct2D では、入力に基づいて効果に精度を割り当てることができない可能性があります。 これは、効果に入力がない場合、または特定の精度がない ID2D1CommandList が使用される場合に発生します。 この場合、中間テクスチャの精度は、コンテキストの現在のレンダー ターゲットとして設定されたビットマップから決定されます。
効果と変換に対する直接的かつ精密な選択
中間テクスチャの最小精度は、エフェクト グラフ内の明示的な位置でも設定できます。 これは、高度なシナリオでのみ推奨されます。
最小有効桁数は、次のように効果のプロパティを使用して設定できます。
if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
hr = Effect->SetValue(D2D1_PROPERTY_PRECISION, D2D1_BUFFER_PRECISION_32BPC_FLOAT);
}
効果の実装内では、次のように ID2D1RenderInfo::SetOutputPrecision を使用して最小有効桁数を設定できます。
if (EffectContext->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
hr = RenderInfo->SetOutputBuffer(
D2D1_BUFFER_PRECISION_32BPC_FLOAT,
D2D1_CHANNEL_DEPTH_4);
}
効果に設定された精度は、同じ効果グラフのダウンストリーム効果に反映されることに注意してください。ただし、それらのダウンストリーム効果に対して別の精度が設定されていない限りです。 エフェクト内の変換に設定された精度は、ダウンストリーム変換ノードの精度には影響しません。
特定の変換ノードの出力を格納する中間バッファーの最小精度を決定するために使用される完全な再帰ロジックを次に示します。