|
Before
After
今回はテッセレーションをやります。テッセレーションとはいわゆるポリゴンの細分化処理を行うことです。 既にいくつかのサイトで紹介されているので今更感がありますが、 Direct3D11 やるならぜひともやっておきたい技術のひとつなのでやります。
テッセレーションの利用目的は LoD( Level of Detail ) などがあげられます。 LoD は視点からの距離に応じて描画する3Dメッシュの頂点数の増減を行う処理のことです。 モデリング時のメッシュはローポリで作成して、アップ時にはテッセレーションによりポリゴン分割して高品質にレンダリングされるようにします。 こうすることでレンダリング品質を落とすことなく、さらに頂点の行列変換にかかる負荷を落としてパフォーマンスの向上が期待できます。 まあ実際の使用方法については次回以降に紹介することにして今回は基礎的なことをやります。
ではテッセレーションの概要を説明していきます。ここでは簡単な説明にとどめますので、詳細を知りたい方はMSDNを参照してください。
テッセレーションは3つのステージで構成されます。
ステージ名 | シェーダー | 目的 |
ハルシェーダーステージ | プログラマブルシェーダー | エッジ テッセレーション係数やパッチ定数データを決定する。 |
テッセレータ ステージ | 固定機能シェーダー | パーティションの種類とエッジ テッセレーション係数をもとにパッチを分割し、uv (およびオプションとして w) 座標を決定する。 |
ドメイン シェーダー ステージ | プログラマブルシェーダー | パッチ定数データとuv (およびオプションとして w) 座標とコントロールポイントをもとに実際の頂点座標を計算する |
次にパイプライン ステージの遷移と入出力パラメータの図を示します。
矢印がいっぱいあってわけわからん状態です。たぶんこんな感じであってると思います。
聞きなれない用語がいくつか出てきましたので、解説します。ですが MSDN に用語の意味は説明されていないので勝手に解釈します。 ですのでもしかすると間違っている可能性があるのでご了承を。
1.コントロールポイント
テッセレータにより追加された頂点の座標をパラメトリック曲面により計算するときに使用する頂点。制御点ともいう。
2.パッチ定数データ
パッチはポリゴン分割処理を行う際に使用する頂点セットのことで、パッチ定数データはパッチごとに指定する定数データのこと。
分割後の頂点の座標を決定する際に使用する。
3.パーティションの種類
ポリゴンの分割時に使用するアルゴリズム。
4.エッジ テッセレーション係数
ポリゴンの分割率を指定する係数。この値が大きくなるほどより詳細に分割される。
5.uv (およびオプションとして w) 座標
テッセレータ ステージから出力される uv 座標は、テッセレーションにより生成された 0 〜 1 の範囲内の補完係数である。
ではソースを見ていきます。
---Tessellation01.hlsl---
どのような場所の値のグラフは次のように見えますか?
// 定数バッファ0 cbuffer cbBuffer0 : register( b0 ) { // 列優先 column_major float4x4 g_matWVP : packoffset( c0 ); // ワールド × ビュー × 射影 行列 }; // 定数バッファ1 cbuffer cbBuffer1 : register( b1 ) { float g_TessFactor : packoffset( c0.x ); // パッチのエッジのテッセレーション係数 float g_InsideTessFactor : packoffset( c0.y ); // パッチ内部のテッセレーション係数 }; // テクスチャー Texture2D g_Tex : register( t0 ); // サンプラーステート SamplerState g_Sampler; // 頂点シェーダーの入力パラメータ struct VS_IN { float3 pos : POSITION; // 頂点座標 float2 texel : TEXCOORD0; // テクセル }; // 頂点シェーダーの出力パラメータ struct VS_OUT { float3 pos : POSITION; float2 texel : TEXCOORD0; }; // ハルシェーダーのパッチ定数フェーズ用の出力パラメータ struct CONSTANT_HS_OUT { float Edges[4] : SV_TessFactor; // パッチのエッジのテッセレーション係数 float Inside[2] : SV_InsideTessFactor; // パッチ内部のテッセレーション係数 }; // ハルシェーダーのコントロール ポイント フェーズ用の出力パラメータ struct HS_OUT { float3 pos : POSITION; float2 texel : TEXCOORD0; }; // ドメインシェーダーの出力パラメータ struct DS_OUT { float4 pos : SV_POSITION; float2 texel : TEXCOORD0; }; // ***************************************************************************************** // 頂点シェーダー // ***************************************************************************************** VS_OUT VS_Main( VS_IN In ) { VS_OUT Out; // 頂点シェーダーではそのまま渡す Out.pos = In.pos; Out.texel = In.texel; return Out; } // ***************************************************************************************** // ハルシェーダーのパッチ定数フェーズ // ***************************************************************************************** CONSTANT_HS_OUT ConstantsHS_Main( InputPatchドメインシェーダーのメイン関数である DS_Main() では分割後の実際の頂点座標を計算します。 uv座標には分割後の 0 〜 1 の範囲内の補完係数です。コントロールポイントの座標から分割後の頂点座標を計算します。ip, uint PatchID : SV_PrimitiveID ) { CONSTANT_HS_OUT Out; // 定数バッファの値をそのまま渡す Out.Edges[0] = Out.Edges[1] = Out.Edges[2] = Out.Edges[3] = g_TessFactor; // パッチのエッジのテッセレーション係数 Out.Inside[0] = g_InsideTessFactor; // パッチ内部の横方法のテッセレーション係数 Out.Inside[1] = g_InsideTessFactor; // パッチ内部の縦方法のテッセレーション係数 return Out; } // ***************************************************************************************** // ハルシェーダーのコントロール ポイント フェーズ // ***************************************************************************************** [domain("quad")] // テッセレートするメッシュの形状を指定する [partitioning("integer")] // パッチの分割に使用するアルゴリズムを指定する [outputtopology("triangle_ccw")] // メッシュの出力方法を指定する [outputcontrolpoints(4)] // ハルシェーダーのコントロール ポイント フェーズがコールされる回数 [patchconstantfunc("ConstantsHS_Main")] // 対応するハルシェーダーのパッチ定数フェーズのメイン関数 HS_OUT HS_Main( InputPatch In, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID ) { HS_OUT Out; // そのまま渡す Out.pos = In[i].pos; Out.texel = In[i].texel; return Out; } // ***************************************************************************************** // ドメインシェーダー // ***************************************************************************************** [domain("quad")] DS_OUT DS_Main( CONSTANT_HS_OUT In, float2 uv : SV_DomainLocation, const OutputPatch patch ) { DS_OUT Out; // 頂点座標 float3 p1 = lerp( patch[1].pos, patch[0].pos, uv.x ); float3 p2 = lerp( patch[3].pos, patch[2].pos, uv.x ); float3 p3 = lerp( p1, p2, uv.y ); Out.pos = mul( float4( p3, 1.0f ), g_matWVP ); // テクセル float2 t1 = lerp( patch[1].texel, patch[0].texel, uv.x ); float2 t2 = lerp( patch[3].texel, patch[2].texel, uv.x ); float2 t3 = lerp( t1, t2, uv.y ); Out.texel = t3; return Out; } // ***************************************************************************************** // ピクセルシェーダ // ***************************************************************************************** float4 PS_Main( DS_OUT In ) : SV_TARGET { return g_Tex.Sample( g_Sampler, In.texel ); }
---main.cpp---
遺伝物質は、爬虫類に渡さ方法
#include "../../USER/DX11User.h" #include "../../USER/D3D11User.h" #include "../../USER/DebugFontUser.h" // コンパイル済み頂点シェーダー #include "../../USER/HLSL/Tessellation01_VS_Main.h" // コンパイル済みハルシェーダー #include "../../USER/HLSL/Tessellation01_HS_Main.h" // コンパイル済みドメインシェーダー #include "../../USER/HLSL/Tessellation01_DS_Main.h" // コンパイル済みピクセルシェーダー #include "../../USER/HLSL/Tessellation01_PS_Main.h" // シェーダーオブジェクトを作成するとき、ファイルから読むか、メモリから読むかを切り替える #if defined(DEBUG) || defined(_DEBUG) #define UNCOMPILED_SHADER // ファイルを読み込んでコンパイルする
0 件のコメント:
コメントを投稿