効果グラフでの精度と数値のクリッピング

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 効果グラフ

グラフ内のすべての隣接するピクセル シェーダーがリンクされているわけではないため、特定のグラフのみがWindows 10で異なる出力を生成します。 詳細については、「 エフェクト シェーダーのリンク」を参照してください。 主な制限事項は次のとおりです。

  • 効果は、最初の効果が複数の効果への入力として接続されている場合、その出力を消費する効果とリンクされません。
  • 最初の効果が出力とは異なる論理位置で入力をサンプリングする場合、効果は入力として効果セットとリンクされません。 たとえば、カラー マトリックス効果は入力とリンクされている可能性がありますが、畳み込み効果はリンクされません。

組み込みの効果の動作

組み込みの効果の多くは、入力色がその範囲内にある場合でも、未乗算色空間の [0, 1] 範囲外の色を生成する場合があります。 このような場合、このような色は数値クリッピングの対象になる可能性があります。 組み込みの効果は通常、事前に乗算された空間で色を生成する場合でも、未乗算領域の色範囲を考慮することが重要であることに注意してください。 これにより、他の効果が後でプリマルチプルされない場合でも、色が範囲内に収まるようにします。

これらの範囲外の色を出力する可能性がある効果の一部は、"ClampOutput" プロパティを提供します。 具体的な内容は次のとおりです。

これらの効果に対して ClampOutput プロパティを TRUE に設定すると、シェーダーのリンクなどの要因に関係なく、一貫した結果が得られます。 クランプは、未乗算空間で発生することに注意してください。

その他の組み込み効果では、色ピクセル (および "Color" プロパティがある場合) がその範囲内にある場合でも、[0, 1] の範囲を超える出力色が生成される場合があります。 具体的な内容は次のとおりです。

エフェクト グラフ内で数値クリッピングを強制する

ClampOutput プロパティを持たない上記の効果を使用する一方で、アプリケーションでは数値クランプを強制することを検討する必要があります。 これを行うには、ピクセルをクランプする追加の効果をグラフに挿入します。 Color Matrix 効果を使用できます。"ClampOutput" プロパティを TRUE に設定し、'ColorMatrix' プロパティを既定の (パススルー) 値のままにします。

一貫性のある結果を得る 2 つ目のオプションは、Direct2D で精度の高い中間テクスチャを使用するように要求することです。 これについては、以下で説明します。

中間テクスチャの精度の制御

Direct2D には、グラフの精度を制御するいくつかの方法が用意されています。 Direct2D で高精度フォーマットを使用する前に、アプリケーションは GPU で十分にサポートされていることを確認する必要があります。 これをチェックするには、ID2D1DeviceContext::IsBufferPrecisionSupported を使用します。

アプリケーションでは、WARP (ソフトウェア エミュレーション) を使用して Direct3D デバイスを作成し、デバイス上の実際の GPU ハードウェアに関係なく、すべてのバッファー精度がサポートされることを保証できます。 これは、ディスクへの保存中に写真に効果を適用するなどのシナリオで推奨されます。 Direct2D が GPU で高精度バッファー形式をサポートしている場合でも、このシナリオでは機能レベル 9.X GPU で WARP を使用することをお勧めします。これは、一部の低電力モバイル GPU でシェーダーの算術演算とサンプリングの精度が制限されているためです。

以下のいずれの場合も、要求された有効桁数は、実際には 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);
}
              

エフェクトに対して設定された精度は、同じ効果グラフのダウンストリーム効果に反映されることに注意してください。ただし、それらのダウンストリーム効果に対して別の有効桁数が設定されていない限りです。 効果内の変換に設定された有効桁数は、ダウンストリーム変換ノードの有効桁数には影響しません。

特定の変換ノードの出力を格納する中間バッファーの最小有効桁数を決定するために使用される完全な再帰ロジックを次に示します。

中間バッファーの最小有効桁数ロジック