GPUBoids サンプル

これは、SIGGraph 2007 の Advanced Real-Time Rendering in 3D Graphics and Games コースで紹介された、3 つのサンプル アプリケーションのうちの 1 つです。Direct3D 10 のサンプルは、GPU で完全に管理される群れアルゴリズムを示しています。

Bb943955.d3d10_sample_GPUBoids(ja-jp,VS.85).jpg

Path

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

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

パーティクル システムは、電灯や倒れた戦士の周りに鳥や虫が群がっているような錯覚を作り出す場合によく使用されます。従来の群れの動作には、もっともらしく見せるために従う必要があるいくつかの単純な規則があります。この例の場合は、衝突回避、距離間隔、凝集、および整列の規則です。群れの動作の詳細については、[Reynolds87, Reynolds99] を参照してください。

力のスプラッティング

力のスプラッティングの目的は、1 つのパーティクルのフォースを単一操作によって他のすべてのパーティクルに射影することです。この例の場合の操作は、クワッド プリミティブのレンダリングになります。使用するテクスチャーと、パーティクルに適用するすべてのフォースの蓄積バッファーを作成します。このバッファーは、ラスター化処理のターゲットになり、パーティクル フォースを蓄積します。フォース テクスチャーの各テクセルには、単一パーティクルに作用する蓄積されたフォースが保持されます。N 個のクワッド プリミティブのスタックも作成します (N はシステム内のパーティクルの数)。クワッドの次元は、ラスター化されるとフォース バッファーを完全に覆うような形になります。スタック内の各クワッドの 4 つの頂点には、クワッドによって表される正確なパーティクルを識別する頂点要素が含まれます。ラスター化を実行すると、この補間された頂点要素を使用して、パーティクル テクスチャーまたはパーティクル バッファーからパーティクルのプロパティがフェッチされます。

Bb943955.d3d10_sample_ForceSplatting1(ja-jp,VS.85).jpg

単一クワッドのラスター化では、ラスター化されるパーティクルと、クワッドの頂点の頂点要素によって表されるパーティクルとの間で、フォースが計算されます。フォースは、加算式のアルファ ブレンディングを有効にして一連のクワッドをレンダリングすることによって蓄積されます。

アルゴリズムの複雑さからいえば洗練性や簡潔性に欠けますが、力のスプラッティング アルゴリズムを使用すると、GPU で複雑な空間分割構造を繰り返し作成しなくても、最新のグラフィック ハードウェアの高速なラスター化能力とアルファ ブレンディング能力を十分に引き出すことができます。

距離間隔と回避

群れのシミュレーションは、前述の N*N の力のスプラッティングを利用してパーティクル間の衝突を回避し、すべてのパーティクルの間に適度な距離間隔を維持します。NBodyGravity サンプルのようにパーティクルが互いに引き合う力を計算するのではなく、ここでは、各パーティクルが反発し合う力を計算します。この計算は、パーティクルが衝突するまでにどの程度近付けるか、またはパーティクル間にどの程度の距離をとるか、に基づいて行います。

float4 PSAccumulateForce(PSForceIn input) : SV_Target
{   
    float3 texcoord = float3( input.tex, 0 );
    float3 vLocalPos = g_txParticleData.SampleLevel( g_samPoint, texcoord, 0 );
    texcoord.z = 1;
    float3 vLocalVel = g_txParticleData.SampleLevel( g_samPoint, texcoord, 0 );
    
    // Check neighbors for separation and avoidance
    float3 vNeighborPos = input.pos;
    float3 delta = vLocalPos - vNeighborPos;
    float r2 = dot( delta, delta );
    float3 vTotalForce = float3(0,0,0);
    if( r2 > 0 )
    {
        vTotalForce = Separation( vLocalPos, vNeighborPos );
        vTotalForce += Avoid( vLocalPos, vLocalVel, vNeighborPos );
    }
    
    return float4(vTotalForce,1);
}

凝集と整列の高速な平均化

凝集や整列などの動作は、パーティクルの平均的な位置と速度の認識に依存します。幸いなことに、最新のグラフィック ハードウェアは、即座にミップマップを生成できるようにしてテクスチャー全体を素早く平均化する手段を備えています。パーティクルの更新フェーズで最小のミップレベルからサンプリングを行うと、パーティクルから凝集の重心に対するフォース ベクトルを作成したり、目的のパーティクルを他のすべてのパーティクルの平均速度で整列させるフォース ベクトルを作成したりできます。このフォース ベクトルは、フォース蓄積テクスチャーからサンプリングされたフォース ベクトルに加算されます。

Bb943955.d3d10_sample_GPUBoids1(ja-jp,VS.85).jpg

次のコードは、テクスチャー内の最小のミップから平均的な位置と速度をサンプリングする方法を示しています。

// Our texcoord is interpolated from the full-screen quad
float3 texcoord = float3( input.tex, 0 );

// Sample the current position in the position texture
float3 pos = g_txParticleData.SampleLevel( g_samPoint, texcoord, 0 );

// Sampling the average position is as easy as sampling any point from the 
// smallest mip map in the position texture.
float3 avgPos = g_txParticleData.SampleLevel( g_samPoint, texcoord, g_iMaxMip );

// Sampling the average velocity is as easy as sampling any point from the 
// smallest mip map in the velocity texture.
texcoord.z = 1;
float4 avgVel = g_txParticleData.SampleLevel( g_samPoint, texcoord, g_iMaxMip );

参考文献

[Reynolds87] C. Reynolds 著。『Flocks, Herds and Schools:A Distributed Behavioural Model』(Computer Graphics、21(4)、1987 年、ページ 25 ~ 34

[Reynolds99] Reynolds、C. W 著。『(1999) Steering Behaviors Forfor Autonomous Characters』(1999 年カリフォルニア州サンノゼ開催の Game Developers Conference 議事録より)。Miller Freeman ゲーム グループ (カリフォルニア州サンフランシスコ)。ページ 763-782.