NBodyGravity サンプル
これは、2007 年 SIGGraph における Advanced Real-Time Rendering in 3D Graphics and Games コースで紹介された、3 つのサンプル アプリケーションのうちの 1 つです。Direct3D 10 のサンプルは、GPU で完全に管理される n ボディ パーティクル システムを示しています。
Path
ソース : | (SDK ルート)\Samples\C++\Direct3D10\NBodyGravity |
実行可能ファイル : | (SDK ルート)\Samples\C++\Direct3D10\Bin\x86 or x64\NBodyGravity.exe |
サンプルが動作するしくみ
このサンプルは、システム内のすべてのパーティクルの相互作用を計算します。この場合の相互作用には、考えられるすべてのパーティクル ペア間の引力が関係してきます。N*N の相互作用の計算には、力のスプラッティングと呼ばれるテクニックを使用します。
力のスプラッティング
力のスプラッティングの目的は、1 つのパーティクルのフォースを単一操作によって他のすべてのパーティクルに射影することです。この例の場合の操作は、クワッド プリミティブのレンダリングになります。使用するテクスチャーと、パーティクルに適用するすべてのフォースの蓄積バッファーを作成します。このバッファーは、ラスター化処理のターゲットになり、パーティクル フォースを蓄積します。フォース テクスチャーの各テクセルには、単一パーティクルに作用する蓄積されたフォースが保持されます。N 個のクワッド プリミティブのスタックも作成します (N はシステム内のパーティクルの数)。クワッドの次元は、ラスター化されるとフォース バッファーを完全に覆うような形になります。スタック内の各クワッドの 4 つの頂点には、クワッドによって表される正確なパーティクルを識別する頂点要素が含まれます。ラスター化を実行すると、この補間された頂点要素を使用して、パーティクル テクスチャーまたはパーティクル バッファーからパーティクルのプロパティがフェッチされます。
単一クワッドのラスター化では、ラスター化されるパーティクルと、クワッドの頂点の頂点要素によって表されるパーティクルとの間で、フォースが計算されます。フォースは、加算式のアルファ ブレンディングを有効にして一連のクワッドをレンダリングすることによって蓄積されます。
float4 PSAccumulateForce(PSForceIn input) : SV_Target
{
float3 inplacePos = g_txParticleData.SampleLevel( g_samPoint,
float3(input.tex, 0),
0 );
// use the law of gravitation to calculate the force of the input
// particle on the particle we're rasterizing across at this moment
float3 delta = input.pos - inplacePos;
float r2 = dot( delta, delta );
float4 force = float4(0,0,0,0);
if( r2 > 0 )
{
// Calculate acceleration between the two caused by gravity
float r = sqrt(r2);
float3 dir = delta/r;
force.xyz = dir * g_fG * ( (g_fParticleMass * g_fParticleMass) / r2 );
}
return force;
}
アルゴリズムの複雑さからいえば洗練性や簡潔性に欠けますが、力のスプラッティング アルゴリズムを使用すると、GPU で複雑な空間分割構造を繰り返し作成しなくても、最新のグラフィック ハードウェアの高速なラスター化能力とアルファ ブレンディング能力を十分に引き出すことができます。
力のスプラッティング
すべてのパーティクルが互いに引き合う力を計算するには、前述の力のスプラッティング手法を使用して、システム内の各パーティクルが受ける力をすべて累算します。パーティクルの更新フェーズでは、この力をパーティクルの量で除算して、パーティクルの瞬間加速度を求めます。動きの方程式が統合され、パーティクル システムが更新されます。