リアルタイム 3D レンダリングで半透明描画が重い話 (1)

それまでコンシューマをやっていたチームが、新たに PC系ビデオカードでゲームを
作ろうと評価を始めると、エフェクトなど半透明の描画が遅いので引っかかって
しまうことがあるようです。

でもよくよく話を聞いているとポリゴンを重ねすぎているだけのように見えます。

半透明の描画が通常のポリゴン描画よりも遅いのは当たり前です。
唯一当たり前じゃなかった特殊なハードが PS2 です。

PS2 には PixelShader どころかマルチテクスチャ等の pixel 演算系機能が無いので
表現力を上げるにはマルチパスを用いる必要がありました。

なのでエフェクトもひたすらポリゴンを重ねて半透明を大量に使う傾向があります。
PS2 は GPU (GS) にオンチップで VRAM を搭載していて、その転送バスは 2560bit
(147MHz で 47GB/sec) もあります。16 pixel/sec と並列度も高く、稀に見る
フィルレートの高さを持っていました。

これなら半透明など Pixel の Read/Write を頻繁に繰り返してもさほど速度が
落ちません。

オンチップでバスの太さを選んだ代わりに容量が犠牲になっており、VRAM はわずか
4M byte しかありませんでした。

4M byte だとフレームバッファだけでも一杯になるので、さらにインターレースを
用いて半分(640×240)で済ませたり、横の解像度を若干削ったり(512)します。

例えば 640×480 で color 32bit, depth 32bit だと 2.4M と半分以上も消費します。
512×240 まで削ると 1Mbyte くらいで収まります。

フレームバッファが小さくなるとさらにフィルの負担が減ることになります。

もちろん半透明といっても、等視点が変わるケースではソートが必要になるため
完全なコストフリーではありません。だけど他のプラットフォームに比べたら
圧倒的に(異常に)速かったわけです。

そんな作り方に慣れてしまっていると他のハードを使ったときに困ってしまいます。

半透明は極力減らすようにとデザイナーに伝えても「前はこうやって作ってたから」
となかなか理解してもらえないのです。

例えば同世代(?)の Xbox は、CPU と共有のバスで 6.4GB/sec の帯域を持っています。
その代わり 64MByte 全部に GPU が直接アクセスできます。

pixel 並列度で 1/4、バスの転送能力で 1/7.5、だけど VRAM は 16倍。そして
マルチテクスチャやプログラマブルなシェーダーを搭載しています。

この場合半透明をひたすら重ねる作り方は自分の首を絞めるようなもので、できる
限り重ね描きを減らさなければなりません。

リッチな表現はマルチテクスチャやシェーダーを使えばいいので、むしろマルチパス
など重ねて描画する必然性が少ないともいえます。

同じようにいまどきの PC のビデオカードも、メモリアクセスが無尽蔵にできる
わけではありません。GPU 自体の膨大な演算能力に比べるとバス帯域はそれなりに
限界があります。

例えば GeForce79000GTX のメモリが 256bit バスの 1600MHz だとすると
51.2GB/sec です。これでもべらぼうに速いんだけど数値上は PS2 の 47GB/sec と
それほど差がありません。

そして PC はよりハイレゾが求められるので、例えば 1920×1200 だと 32bit color,
32bit depth のフレームバッファだけで 18Mbyte です。
たったこれだけでも必要な転送量は 7~18倍 にもなってしまいます。
HDR をまじめにやると color は 64bit です。

この描画面積を考えると PS2 比の転送能力はずっと落ちていくことになります。

それだけ PS2 が特殊だったといえます。

できる限りピクセルを重ねずに、ピクセル1つにかける演算を重視します。
GC, Xbox1, Xbox360, PS3, PC (D3D9) と、その傾向は徐々に強くなっています。

半透明が重いのは当たり前という前提でまず描画の設計を見直しましょう。