ラスタライザー ステージの基礎知識 (Direct3D 10)
ラスタライザー ステージは、次の機能によって制御されます。
- ビューポートの設定
- シザー矩形の設定
- ラスタライザー ステートの設定
ビューポートの設定
ビューポートは、(クリップ空間内の) 頂点の位置をレンダー ターゲットの位置にマップします。この手順では、3D の位置が 2D 空間にスケーリングされます。レンダー ターゲットは、Y 軸に沿って下方向に配置されます。そのため、ビューポートのスケーリング時に Y 座標を反転する必要があります。さらに、x エクステントと y エクステント (x 値と y 値の範囲) は、次の式に従ってビューポートのサイズに合うようにスケーリングされます。
X = (X + 1) × Viewport.Width × 0.5 + Viewport.TopLeftX
Y = (1 - Y) × Viewport.Height × 0.5 + Viewport.TopLeftY
Z = Viewport.MinDepth + Z * (Viewport.MaxDepth - Viewport.MinDepth)
チュートリアル 1 では、D3D10_VIEWPORT を使用し、ID3D10Device::RSSetViewports を呼び出して、640 × 480 のビューポートを作成します。
D3D10_VIEWPORT vp[1];
vp[0].Width = 640.0f;
vp[0].Height = 480.0f;
vp[0].MinDepth = 0;
vp[0].MaxDepth = 1;
vp[0].TopLeftX = 0;
vp[0].TopLeftY = 0;
g_pd3dDevice->RSSetViewports( 1, vp );
ビューポートの記述は、ビューポートのサイズ、深度をマップする範囲 (MaxDepth および MinDepth を使用)、およびビューポートの左上の位置を指定します。MinDepth は MaxDepth 以下でなければなりません。MinDepth と MaxDepth の範囲はどちらも、0.0 ~ 1.0 です (それぞれの値を含みます)。ビューポートの場合、レンダー ターゲットにマップするのが一般的ですが、必須ではありません。また、ビューポートのサイズや位置をレンダー ターゲットと同じにする必要はありません。
ビューポートの配列を作成できますが、ジオメトリ シェーダーから出力された 1 つのプリミティブに適用できるのは 1 つだけです。一度にアクティブに設定できるビューポートは 1 つだけです。パイプラインでは、ラスター化時にデフォルトのビューポート (および次のセクションで説明するシザー矩形) を使用します。デフォルトは、常に、配列内の最初のビューポート (またはシザー矩形) です。ジオメトリ シェーダーでビューポートをプリミティブ単位で選択するには、GS 出力シグネチャ宣言の適切な GS 出力要素で ViewportArrayIndex セマンティクスを指定します。
一度にラスタライザー ステージにバインドできるビューポート (およびシザー矩形) の最大数は 16 です (D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE によって指定されています)。
シザー矩形の設定
シザー矩形は、出力結合ステージに送信されるピクセル数を減らすもう 1 つの手段です。シザー矩形外部のピクセルは破棄されます。シザー矩形のサイズは、整数で指定します。ラスター化時に 1 つの三角形に適用できるシザー矩形は 1 つだけです (System-Value セマンティクスの ViewportArrayIndex に基づきます)。
シザー矩形を有効にするには、(D3D10_RASTERIZER_DESC の) ScissorEnable メンバーを使用します。デフォルトのシザー矩形は、すべての矩形の値が 0 の空の矩形です。つまり、シザーが有効なときにシザー矩形を設定しなかった場合、出力結合ステージにピクセルが送られません。シザー矩形は、ビューポートのサイズに初期化するのが最も一般的な設定です。
シザー矩形の配列をデバイスに設定するには、D3D10_RECT で ID3D10Device::RSSetScissorRects を呼び出します。
D3D10_RECT rects[1];
rects[0].left = 0;
rects[0].right = 640;
rects[0].top = 0;
rects[0].bottom = 480;
D3DDevice->RSSetScissorRects( 1, rects );
このメソッドは、2 つのパラメーターを取得します。それらは、(1) 配列内の矩形の数、および (2) 矩形の配列です。
パイプラインでは、ラスター化時にデフォルトのシザー矩形のインデックスを使用します (デフォルトは、サイズがゼロの矩形で、クリッピングが無効になっています)。これを上書きするには、GS 出力シグネチャ宣言の GS 出力要素に SV_ViewportArrayIndex セマンティクスを指定します。この結果、GS ステージでは、この GS 出力要素がこのセマンティクスによってシステム生成要素としてマークされます。ラスタライザー ステージでは、このセマンティクスが認識され、シザー矩形のインデックスとしてアタッチされたパラメーターを使用して、シザー矩形の配列にアクセスします。必ず、ラスタライザー オブジェクトを作成する前に、ラスタライザー ステージで、定義したシザー矩形を使用するように指定してください。そのためには、ラスタライザーの記述で ScissorEnable 値を有効にします。
ラスタライザー ステートの設定
Direct3D 10 では、ラスタライザー ステートはラスタライザー ステート オブジェクトにカプセル化されます。最大 4096 個のラスタライザー ステート オブジェクトを作成することができます。これらは、ステート オブジェクトにハンドルを渡すことで、デバイスに設定することができます。
ID3D10Device::CreateRasterizerState を使用して、ラスタライザーの記述 (D3D10_RASTERIZER_DESC を参照) からラスタライザー ステート オブジェクトを作成します。
ID3D10RasterizerState * g_pRasterState;
D3D10_RASTERIZER_DESC rasterizerState;
rasterizerState.FillMode = D3D10_FILL_SOLID;
rasterizerState.CullMode = D3D10_CULL_FRONT;
rasterizerState.FrontCounterClockwise = true;
rasterizerState.DepthBias = false;
rasterizerState.DepthBiasClamp = 0;
rasterizerState.SlopeScaledDepthBias = 0;
rasterizerState.DepthClipEnable = true;
rasterizerState.ScissorEnable = true;
rasterizerState.MultisampleEnable = false;
rasterizerState.AntialiasedLineEnable = false;
pd3dDevice->CreateRasterizerState( &rasterizerState, &g_pRasterState );
この一連のステートの例では、最も基本的だと思われるラスタライザーのセットアップが行われます。
- ソリッドの描画モード
- 面のカリングまたは削除 (プリミティブのワインディング順序が反時計回りであることを前提とします)
- 深度バイアスをオフにして、深度バッファーを有効にし、シザー矩形を有効にする
- マルチサンプリングと線のアンチエイリアシングをオフにする
さらに、基本的なラスタライザーの操作では、常に、(視錘台への) クリッピング、パースペティクブ除算、およびビューポートのスケーリングが行われます。ラスタライザー ステート オブジェクトを正常に作成したら、次のようにデバイスに設定します。
pd3dDevice->RSSetState(g_pRasterState);
マルチサンプリング
マルチサンプリングは、イメージの一部または全部の要素を高い解像度でサンプリングし、ポリゴンのエッジの描画によって生じるエイリアスの最も明らかな形状を低減します。マルチサンプリングにはサブピクセルのサンプルが必要ですが、最新の GPU ではマルチサンプリングが実装されており、ピクセル シェーダーがピクセルごとに 1 回実行されます。これによって、(特に GPU の制約を受けるアプリケーションの) パフォーマンスと最終的なイメージのアンチエイリアシングとの間のトレードオフが実現します。
マルチサンプリングを使用するには、ラスター化の記述で Enable フィールドを設定し、マルチサンプリングするレンダー ターゲットを作成します。さらに、サンプルを 1 つのピクセル カラーに解決するために、シェーダーでレンダー ターゲットを読み取るか、ビデオ カードを使用してサンプルを解決するために、ID3D10Device::ResolveSubresource を呼び出します。最も一般的なシナリオは、マルチサンプリングした 1 つまたは複数のレンダー ターゲットに描画することです。
マルチサンプリングは、サンプル マスクを使用しているかどうか、アルファトゥカバレッジが有効かどうか、およびステンシル処理 (常にサンプル単位で実行されます) に依存しません。
深度テストは、マルチサンプリングの影響を受けます。
- マルチサンプリングを有効にすると、サンプル単位で深度が補間され、サンプル単位で深度/ステンシル テストが実行されます。合格したすべてのサンプルで、ピクセル シェーダーの出力カラーが重複します。ピクセル シェーダーが深度を出力する場合、すべてのサンプルで深度値が重複します (このシナリオでは、マルチサンプリングの利点がなくなります)。
- マルチサンプリングを無効にしても、深度/ステンシル テストはサンプル単位で実行されますが、深度はサンプル単位で補間されません。
1 つのレンダー ターゲット内でマルチサンプリング レンダリングと非マルチサンプリング レンダリングを混合することについて、制限はありません。マルチサンプリングを有効にして、非マルチサンプリング レンダー ターゲットに描画した場合、マルチサンプリングが有効になっていない場合と同じ結果になります。サンプリングは、ピクセルごとに 1 つのサンプルで実行されます。