PostProcess サンプル

このサンプルでは、インタラクティブに実現できる興味深いイメージ処理エフェクトを示します。これまでのイメージ処理は、ホスト CPU で相当量のプロセッサ電力を消費するため、通常はオフラインで行われていました。ピクセル シェーダーを使用することによってこれらのエフェクトをハードウェアで効率よく処理できるため、リアルタイムでの適用が可能になります。

ここに示すテクニックには、ピクセル シェーダー 2.0 と浮動小数点テクスチャーが必要です。したがって、すべてのカードですべてのポストプロセッシング テクニックがサポートされるわけではありません。

Bb147283.PostProcessIntro(ja-jp,VS.85).jpg

Path

ソース : (SDK ルート)\Samples\C++\Direct3D\PostProcess
実行可能ファイル : (SDK ルート)\Samples\C++\Direct3D\Bin\x86 or x64\PostProcess.exe

ポストプロセッシング エフェクト

イメージ処理テクニックによってシーンの質とリアリティを向上できるだけでなく、シーン全体のぼかしといった特定のエフェクトを得ることもできます。Direct3D では、イメージ処理は通常、レンダリング完了後のポストプロセッシングとして行われます。アプリケーションでは、最初にシーンをテクスチャー上にレンダリングし、その後でピクセル シェーダーを使ってテクスチャーを処理し、拡張や変更を加えることによって別のイメージを生成します。ピクセル シェーダーを使用することによってこの操作の効率が大きく向上し、リアルタイムで処理できるようになります。

ポストプロセッシング エフェクトによって、特に一連のポストプロセッシングが元のシーンに適用された場合に興味深い結果が得られます。このサンプルには、次の 4 つのポストプロセッシング エフェクトが組み込まれています。

  • ブラー - ピクセルの色を周辺ピクセルの色と組み合わせて、焦点をぼかします。
  • ブルーム - イメージ内のブライト スポットと、ブライト スポット周辺の領域を拡大します。
  • 被写界深度 - ピクセルの深度または z 値に基づいて、ピクセルをぼかします。非常に離れているピクセル、または非常に近いピクセルにぼかしが加えられます。
  • エッジ グロー - オブジェクトの法線を使ってオブジェクトのエッジを見つけ出し、ぼかしを利用してエッジ上にグローを生成します。

サンプルが動作するしくみ

シーンには、テクスチャー処理または環境マッピング処理が可能なメッシュ オブジェクトと、スカイボックス キューブ形式の背景が含まれています。サンプルは 2 つの部分に分けることができます。最初の部分では、シーン データが 3 つのソース レンダー ターゲットにレンダリングされ、2 番目の部分では、ピクセル シェーダーを使用して 2D エフェクトが 3 つの対象レンダー ターゲットに実装されます。

サンプルのパート 1 は、ピクセルごとのデータを 3 つのシーン レンダー ターゲット、0、1、2 にレンダリングします。

Bb147283.PostProcessSwapChain(ja-jp,VS.85).gif

サンプルのパート 2 では、3 つのシーン レンダー ターゲットとソース レンダー ターゲット (0、1、2) からソース マテリアルを使用し、ピクセル シェーダーを使って全画面クワッドを対象レンダー ターゲット (3、4、5) にレンダリングします。パート 2 の 6 つのレンダー ターゲットは、図の曲線矢印で示されている 3 つのスワップ チェーンに編成されます。ピクセル シェーダーが処理を完了すると、対象レンダー ターゲットはそれぞれのソース レンダー ターゲットと交換されます。その結果、このサンプルを使用してポストプロセッシング済みのエフェクトを重ねて表示することができます。たとえば、[Color] Monochrome ([色] モノクロ) はポストプロセッシング エフェクトの 1 つであり、カラー ソース テクスチャー (ターゲット 3) をサンプリングし、それをグレースケールに変換した後で、その結果をカラー チャンネル (ターゲット 6) 用にスワップ チェーン内の他のテクスチャーに出力します。

すべてのポストプロセッシング エフェクトで 3 つのレンダー ターゲットがすべて必要とされるわけではありません。ただし、3 つのレンダー ターゲットを使用すると、ポストプロセッシング エフェクトに利用可能なオプションが増えます。通常、カラー レンダー ターゲットは更新され、置換されます。ただし、他のテクスチャーを置換できるようにすることで、柔軟性が高まります。このサンプルのアーキテクチャで、法線テクスチャーと位置テクスチャーを変更する独創的なポストプロセッシング エフェクトが可能となります。レンダリング可能なポストプロセッシング エフェクトの数を制限するものは、システム リソースのみです。

サンプル プログラムの実行

サンプルが実行されると、ユーザーに対して標準的な Direct3D サンプル ウィンドウと、次のような [Select Post Process Effects] ダイアログが表示されます。

Bb147283.PostProcessDialog(ja-jp,VS.85).png

ダイアログの上部には、2 つのリスト コントロールが表示されます。最初のリストには、利用可能なポストプロセッシング エフェクトが表示されます。2 番目のリストには、アクティブなエフェクトが表示されます。シーンがレンダリングされた後で、シーン イメージにアクティブなポストプロセッシング エフェクトが一覧表示順に適用され、その後で結果がユーザーに表示されます。ユーザーがアクティブなリストを変更すると、シーンへのビジュアル変更が直ちに反映されます。

リストの下には、エフェクトを適用する順序を変更するためのボタンが表示されます。このボタンは、リストのクリアにも使用できます。パラメーター セクションでは、ユーザーが調整してさまざまなビジュアル表現を生成できるパラメーターが、一部のエフェクト (ブライト パスなど) に割り当てられています。アクティブなポストプロセッシングにパラメーターが割り当てられている場合、ユーザーはそのポストプロセッシングを強調表示して、パラメーターを調節できます。

下部には、さまざまなポストプロセッシング エフェクトを組み合わせてより面白く表現できる方法を示す、事前定義されたポストプロセッシングの組み合わせが表示されます。

エフェクト ファイル

それぞれのポストプロセッシングは、1 つの D3DX エフェクト ファイルに実装されています。ポストプロセッシング エフェクトが必要なときに選択される各ファイルに、PostProcess というテクニックが格納されています。このテクニックには、1 つ以上のパスを割り当てることができます。それぞれのパスは、呼び出されたときに実際のイメージ処理を行うピクセル シェーダーを指定します。このテクニックには、ピクセル シェーダーからの出力先テクスチャーを指定する nRenderTarget という整数の注釈を割り当てることができます。この注釈に値 0、1、または 2 を割り当てて、ピクセル シェーダーの出力をそれぞれ色、法線、または位置テクスチャーに書き込むことを指定します。この注釈がない場合、出力はカラー テクスチャー用と見なされます。

オプションとして、パスに 2 つの浮動小数点注釈、fScaleX および fScaleY を割り当てることができます。この 2 つの値は、出力イメージがレンダー ターゲットに書き込まれる前にスケーリングされる量を指定します。ポストプロセッシングによってイメージがレンダー ターゲット テクスチャーよりも小さなサイズにスケーリングされると、再度スケーリングされるまで、後続のすべてのポストプロセッシングでそのイメージ サイズが使用されます。この場合は、ピクセル シェーダーで処理されるピクセル数が少なくなるため、パフォーマンスが大幅に改善されます。一般的なポストプロセッシングの方法として、イメージを縮小し、テクスチャーのサブ領域にポストプロセッシング エフェクトを適用した後で、そのイメージを元のサイズに拡大します。処理するピクセル数を減らすことで得られるパフォーマンスの改善は、余分なスケーリング ステップを実行するというペナルティをはるかに凌ぎます。

エフェクト ファイルには、ポストプロセッシング ピクセル シェーダーがサンプリングに使用するサンプラーを持つ 6 つのテクスチャー オブジェクトが格納されています。g_txSrcColor、g_txSrcNormal、および g_txSrcPosition には、前のポストプロセッシングの結果から得られた色、法線、およびカメラ空間位置が格納されています。g_txSceneColor、g_txSceneNormal、および g_txScenePosition は、シーン レンダラーの成果物です。シーケンスで最初のポストプロセッシングの場合、この 2 セットのテクスチャーは同じです。

ポストプロセッシング ピクセル シェーダーは、1 つの対象ピクセルを生成するために、ソース テクスチャーを複数回、1 回ごとに対象ピクセルの付近の異なる場所でサンプリングしなければならない場合があります。その場合は、エフェクト ファイルで対象ピクセルからのテクセル オフセットの配列 (float2) であるカーネルを宣言します。その後に、エフェクト ファイルで同じサイズの配列 float2 をもう 1 つ定義します。この 2 番目の配列には、最初のカーネル配列の名前が含まれている文字列注釈 ConvertPixelsToTexels があります。サンプルは、エフェクト ファイルを読み込んでこの注釈を確認すると、オフセットをピクセル座標から tex2D (DirectX HLSL) などのテクスチャー サンプリング関数に対応するテクセル座標に変換します。ソース テクセルがサンプリングされると、カーネル内のオフセットがテクスチャー座標に追加されて、対象ピクセルの付近のテクセル値が取得されます。

エフェクトの中には、ユーザーが調節できるパラメーターを使用するものがあります。たとえば、ブライト パス エフェクトには、さまざまなビジュアル表現を与えるためにユーザーが調整できるパラメーターがあります。それぞれの PostProcess テクニックでは、この目的のために 1 つ以上の注釈を定義できます。1 つのテクニックでサポートされるパラメーターの最大数は 4 です。

注釈名 説明
Parameter0 string ユーザーが調整可能な変数名が含まれています。
Parameter0Def float4 Parameter0 のデフォルト値です。この型は常に float4 です。必要な浮動小数点が 4 つ未満の場合は、Parameter0Size を使用してそれを指定します。
Parameter0Size int 使用される Parameter0 の成分の数を指定します。2 の場合は、最初の 2 つの成分 (x と y) のみが使用されます。
Parameter0Desc string このパラメーターを記述する文字列です。

サンプル コード

サンプル コードでは、それぞれのポストプロセッシング エフェクトの種類が CPostProcess クラスによって表されています。このクラスは、エフェクト ファイルをカプセル化し、エフェクト テクニックを有効化したり、そのパラメーターを変更したりするためのメカニズムを提供します。初期化時に、CPostProcess オブジェクトの配列が、ポストプロセッシング エフェクト ファイルごとに 1 つずつ作成されます。

アクティブなポストプロセッシング エフェクトのリストでは、各エントリが CPProcInstance クラスによって表されています。このクラスには、このポストプロセッシングに適用されるエフェクトとパラメーターを示す CPostProcess 配列へのインデックスのみが含まれています。

サンプルの Render メソッドはまず、レンダー ターゲット テクスチャーのセットにシーンをレンダリングします。ここでは、色、法線、位置に対して 3 つのレンダー ターゲットが同時に使用されます。これが完了した後で、PerformPostProcess を呼び出します。これは、シーン イメージにポストプロセッシングを適用する際のすべての局面を処理します。PerformPostProcess が戻った後で、コードは IDirect3DDevice9::StretchRect を呼び出してポストプロセッシングの結果をデバイス バック バッファーにコピーし、ユーザーに最終的なイメージが表示されるようにします。

ポストプロセッシングは、2 つの関数、PerformPostProcess および PerformSinglePostProcess で行われます。

PerformPostProcess は最初に、ポストプロセッシングに対してレンダリングを実行する方法を定義するクワッドを設定します。次に、作成したクワッドを格納する頂点バッファーを作成します。その後は、アクティブなエフェクトのリストを反復処理し、リスト内のエントリごとに PerformSinglePostProcess を呼び出します。

PerformSinglePostProcess は、レンダー ターゲット テクスチャーにポストプロセッシング エフェクトを 1 回適用します。まず、エフェクトのテクスチャーとパラメーターを初期化します。次に、ループに入って、このテクニックのすべてのパスをレンダリングします。パスごとにスケーリング値をチェックし、クワッドに必要な調整を加えます。その後で、IDirect3DDevice9::DrawPrimitive を呼び出して、クワッドをレンダー ターゲット テクスチャーにレンダリングします。最後に、レンダー ターゲット テクスチャーを対応するソース テクスチャーと交換して、読み込みや書き込みの対象となる適切なテクスチャーが次のポストプロセッシング に割り当てられるようにします。

次のセクションでは、このサンプルに含まれている一連のポストプロセッシングを示し、それぞれの動作を説明します。

ポストプロセッシング

名前 実装ファイル 説明
[Color] Monochrome ([色] モノクロ) PP_ColorMonochrome.fx カラー イメージをモノクロに変換します。
[Color] Gaussian Blur Horizontal ([色] ガウス ブラー水平) PP_ColorGBlurH.fx 水平方向のガウス ブラーを実行します。ピクセル シェーダーは、ソース テクスチャー座標の左右に対して複数のテクセルをサンプリングし、サンプル間の加重平均を行うことで、これを実行します。
[Color] Gaussian Blur Vertical ([色] ガウス ブラー垂直) PP_ColorGBlurV.fx 垂直方向のガウス ブラーを実行します。ピクセル シェーダーは、ソース テクスチャー座標の上下に対して複数のテクセルをサンプリングし、サンプル間の加重平均を行うことで、これを実行します。
[Color] Bloom Horizontal ([色] ブルーム水平) PP_ColorBloomH.fx 水平方向のガウス ブラーを実行すると同時に、イメージを拡大します。
[Color] Bloom vertical ([色] ブルーム垂直) PP_ColorBloomV.fx 垂直方向のガウス ブラーを実行すると同時に、イメージを拡大します。
[Color] Bright Pass ([色] ブライト パス) PP_ColorBrightPass.fx イメージ上でブライト パスを実行します。輝度は調節可能です。
[Color] Tone Mapping ([色] トーン マッピング) PP_ColorToneMapping.fx イメージ上でトーン マッピングを実行します。輝度は調節可能です。
[Color] Edge Detection ([色] エッジ検出) PP_ColorEdgeDetect.fx カラー テクスチャーを基準としてエッジ検出を実行します。シェーダーは、ピクセル シェーダー パスごとに、テクセルをテクスチャー座標と 4 つの隣接テクセルでサンプリングします。その後で、このテクセルと、それぞれの隣接テクセルとの間の差異を計算します。最後に、シェーダーは 4 つの差異の絶対値を合計し、それを出力します。最終結果として、ピクセルの色が隣接するピクセルの色と大きく異なっている場合、ポストプロセッシングによって得られたピクセルは明るくなります。
[Color] Down Filter 4x ([色] ダウン フィルター 4x) PP_ColorDownFilter4.fx ダウンフィルタリング パスを実行します。使用されるサイズは、オリジナルの 0.25 倍です。ダウン フィルターによってイメージが縮小されます。
[Color] Up Filter 4x ([色] アップ フィルター 4x) PP_ColorUpFilter4.fx アップフィルタリング パスを実行します。使用されるサイズは、オリジナルの 4 倍です。アップ フィルターによってイメージが拡大されます。
[Color] Combine ([色] 組み合わせ) PP_ColorCombine.fx 前のポストプロセッシングの結果と元のシーンを組み合わせて、その合計を出力します。
[Color] Combine 4x ([色] 組み合わせ 4x) PP_ColorCombine4.fx 前のポストプロセッシングの結果と元のシーンを組み合わせて、その合計を出力し、さらに 4 倍のアップフィルタリング パスを実行します。
[Normal] Edge Detection ([法線] エッジ検出) PP_NormalEdgeDetect.fx [Color] Edge Detection ([色] エッジ検出) と同様のエッジ検出を実行しますが、このテクニックでは比較の対象が色ではなく、隣接テクセルの法線である点が異なります。色ベースの方法と比較した場合のこの方法の利点は、テクスチャー パターンがエッジとして扱われないことです。
DOF Combine (DOF 組み合わせ) PP_DofCombine.fx ピクセルの z 座標を基準として、前のポストプロセッシングで得られたテクセルと元のイメージとの間で線形補間を実行します。焦点面を表すベクトル パラメーターを使用して、2 つのソース テクスチャーから重みを決定します。
Normal Map (法線マップ) PP_NormalMap.fx ピクセルの法線 (法線テクスチャー上のテクセル) を取り込み、それを色として出力します。これは、シーンで法線を視覚化する手段として提供されています。
Position Map (位置マップ) PP_PositionMap.fx ピクセルの位置 (位置テクスチャー上のテクセル) を取り込み、色として z 値を出力します。これは、シーンで深度情報を視覚化する手段として提供されています。

ブラー

ブラーはごく一般的なイメージ ベースのエフェクトであり、わかりやすいものです。まず、描画されるピクセル数を減らすために (したがってパフォーマンスを改善するために)、ダウン フィルターが実行されます。次に、水平ブラーと垂直ブラーが 1 回ずつ実行されます。それ以上のブラーリングが必要であれば、ブラー エフェクトを繰り返し実行します。最後に、アップ フィルターを実行してイメージを元のサイズに戻します。

ブルーム

ブルームによって得られる視覚的な効果は、シーンのブライト スポットが拡大され、スポット周辺の領域が明るくなることです。これを実現するには、最初に 2 つのダウン フィルター パスを実行します。ブライト スポットの抽出にはそれほどの詳細が必要とされないため、2 つのダウン フィルターのパスによって、質を落とすことなくパフォーマンスが向上します。次に、ブライト パスが実行されます。このポストプロセッシングでは、イメージ内で一定のしきい値を上回る領域がピックアップされ、それを白くした後で、イメージの残りの領域を黒にします。この後、水平ブルームと垂直ブルームそれぞれに対応する 2 つの代替パスが実行されます。最後に、2 つのアップ フィルターのパスが実行され、その結果が元のイメージと組み合わされます。2 番目のアップ フィルター パスと組み合わせは 1 つのエフェクト、[Color] Combine 4x ([色] 組み合わせ 4x) で処理されることに留意してください。

被写界深度

被写界深度 (DOF) エフェクトは、ピクセルの z 距離に基づいてイメージのピクセルをぼかします。この実行に必要なステップはブラー エフェクトの場合と同じですが、DOF Combine (DOF 組み合わせ) エフェクトがシーケンスの終わりに追加される点が異なります。DOF Combine (DOF 組み合わせ) の前に、サンプリングに使用可能な 2 つのテクスチャーがあります。つまり、前のポストプロセッシングでぼかしが適用されたイメージと、元のぼかしのないイメージです。DOF Combine (DOF 組み合わせ) では、各ピクセルで z 座標を調べ、2 つのテクスチャー間で線形補間を行うことによって色を計算します。

エッジ グロー

このエフェクトは、イメージを取り込んでその一部に色を付け、それ以外の部分をすべて黒にして元のイメージと組み合わせるブルームと、概念上は非常によく似ています。エッジ グローの場合、強調される領域はシーンのエッジ周辺です。まず、法線ベースのエッジ検出が行われます。これによって、イメージのエッジに沿って白の線が生成されます (この場合、法線は隣接するピクセル間で大幅に変化します)。次に、ダウンフィルタリング、ブラーリング、およびアップフィルタリングによってブラー エフェクトが実行されます。最後に、結果が元のイメージと組み合わされて、エッジに沿ってグロー効果が生み出されます。アップフィルタリングと最後の組み合わせは、1 つのエフェクトで処理されることに留意してください。