拙訳
- “Expression Language”テキストモデルでオーサリングして、ツールでPSSLにコンパイルする
- 位置、サイズ、色等を操作する式の集合で記述される
- PSSLはPlayStationのシェーダー言語
データ構造
- Draw records
- 描画に必要な情報の配列
- 位置、色、アルファ、方向、マテリアルテーブルへのインデックス、など
- 不透明半透明両方の描画で使われる
- 描画に必要な情報の配列
- Sort resords
- 対応するDraw recordへの参照(8B)のリスト
- 透明描画で使われる
- マテリアルテーブル:
- テクスチャへの参照、UV warping情報、など
- テクスチャアトラス:
- パーティクルシステムが管理するテクスチャ配列
- 512x512、256x256、128x128、64x64の4種類に分かれる
非同期CS
- フロー:
- Emit:
- 新しく発生したパーティクルを追加する
- Update:
- 状態の更新やパーティクルの消失を行う
- Draw recordsとSort recordsを出力する
- Ribbonize:
- Sort:
- 透明パーティクルを後ろから前に整列させる
- バイトニックソートが使えるが、スケールしにくい
- パーティクル数が増えると、データ移動やパス数が増える
- マージソートはバイトニックソートより実環境で2倍から10倍早かった
- Emit:
- 乱数
static float s_uSeed = uSeed + iThread % 100.1234;
static float s_uRand = 0;
float URand()
{
s_uRandSeed += 3.0;
float g = s_uRand + s_uRandSeed;
float gSquared = g * g / 1.141592653589793;
return s_uRand = gSquared - floor(gSquared);
}描画
- 不透明
- 順不同でGバッファに書き込む
- GPUで個数を数えて、エミッタごとに1ドローコール
- パーティクルごとにSHライティング
- ディストーション付きパーティクルは専用バッファに書き込む
- ポストプロセスで適用
- Ripples
- 順不同でGバッファに書き込む
- 透明
- 頂点IDを使って手動でインスタンス化する
- シェーダを1種類のみ使用して、ソートしてドローコール1つにまとめる
- Sort recordを介して自分のDraw recordにアクセスする
- カリングせず、半透明シャドウマップの描画にも同じリストを使う
- UV warping、パーティクル毎のSHライティング、加算や補完のブレンディング、シャドウ、ヘイズ、などが適用される
- 完全なエミッシブから半透明までlerpできる
- シャドウはグローバルシャドウマップの最低解像度カスケードを参照する
- エッジがガタガタに見えたりするので、安価なハックとして、クアッドを湾曲しているとみなして法線をもとにシェーディングを行う
- 深度ベースのヘイズを適用してから描画される
- 遠方のパーティクルでヘイズが消失しないようエフェクトを再適用する必要があるため
- パーティクルの深度が深度バッファと近いところに任意の色を与える
- 重い透明パーティクルは低解像度バッファで描画する
- エッジのアーティファクトを軽減するため、バイラテラル・アップサンプリングして合成する
- 透明シャドウ
- パーティクルを描画してアルファを書き出す
- 背面のキャストを防止するように深度をサンプリングする
- カスケード・シャドウマップの解決時に、通常のPCFハードシャドウと組み合わせる
- タイルベースのディファードライティングで動的ライトを扱う