連載
西川善司連載 / 完全理解「3DMark Vantage」(1)グラフィックスエンジン・前
3DMark Vantageがついにリリースされた。
Windows Vista専用で,DirectX 10世代プログラマブルシェーダ4.0仕様(Shader Model 4.0,以下SM4.0)のGPUが必須というシステム要件については2008年4月28日の記事で伝えられているとおりだが,最新世代の3Dゲームタイトルが,次第にWindows Vista環境を想定してきていることを考えると,筆者個人としては妥当な判断だと思う。
これまでの3DMarkシリーズと同様,今回も「Futuremarkが考えた」という留保は与えられるものの,「次世代3Dゲームのグラフィックス処理やCPUオペレーションはこうなる」という想定のもと,3DMark Vantageは開発された。本連載では以後数回に亘(わた)って,同ベンチマークアプリケーションの技術的解説を行っていき,Futuremarkの考えに迫ってみたいと考えている。
第1回となる本稿では,3DMark Vantageのホワイトペーパーを基に,同アプリケーションのグラフィックスエンジンについて見ていくことにしたい。
まず,大まかなエンジンの流れだが,以下の6ステップからなるとFuturemarkは説明している。
- GPUによるシミュレーションパス
- 影生成のためのシャドウマップ生成パス
- 先行Zバッファレンダリング
- 不透明材質のライティング
- 透明/半透明材質のライティング
- ポストプロセス
それぞれについて,踏み込んで解説してみることにしよう。
3DMark Vantageでは一部のシミュレーション計算を,CPUではなくGPUで行っている。そして,GPUを利用したシミュレーションは,頂点シェーダ(Vertex Shader)やジオメトリシェーダ(Geometry Shader)を活用した頂点レベルのシミュレーションと,ピクセルシェーダ(Pixel Shader)を活用したテクスチャレベルのシミュレーションとに大別できる。
●頂点レベルのシミュレーション
頂点レベルのシミュレーションは,「Graphics Test 1: Jane Nash」における水陸両用機にかけられた布,あるいは「Feature Tests: Cloth Simulation Test」の旗などが代表例だ。
頂点レベルのシミュレーションでは,DirectX 10パイプラインで新設されたストリームアウト(Stream Out)の機能を活用しているという。ストリームアウトとは,頂点シェーダからの出力をバッファに書き出し,再び頂点シェーダに戻すことができる機能のことで,3DMark Vantageではこの機能を使い,頂点シェーダが行ったシミュレーション結果を再び頂点シェーダに戻して,今度はこれを基にして速やかにグラフィックス処理へ取りかかれるようにしている。
ちなみにDirectX 9世代のプログラマブルシェーダ3.0(Shader Model 3.0,以下SM3.0)仕様には,この機能はなかったので,いったん頂点シェーダユニットで出力した内容を,必ず一度ピクセルシェーダユニットのパイプラインを経てから頂点シェーダユニットへ戻す処理が必要だった。
そのほか,火花や水しぶき,塵(ちり)のようなパーティクルに対するシミュレーションも頂点シェーダによって行われている。パーティクルに対するシミュレーションは3Dゲームグラフィックスでよく用いられるベルレ積分法(Verlet Intergration)が利用されているとのこと。ベルレ積分は「前の状態と現在の状態の差分情報から次状態のベクトルを算出する」離散的な積分方法で,GPUで処理するのに向いている。
なおFuturemarkは,DirectX 10の新機能である「DrawAuto」は使用しなかったとしている。DrawAutoとは,CPU側のエンジン処理と非同期で,GPU内部で描画を勝手に開始してしまう機能で,CPUに“お伺い”を立てることなく,必要な情報さえ揃っていればGPU側で自動描画してしまえるので,処理の高速化に結びつく。しかし,3DMark Vantageのエンジンでは,シミュレーション処理後のパーティクルの状態をCPU側(=エンジン側)で保存,参照する設計になっているため,描画後はCPU(=エンジン)に結果を返す必要がある。そのため,CPUと非同期でGPUが勝手に処理を進めてしまうDrawAutoは逆に不都合だったというわけだ。
もっともFuturemarkは,「CPU側が関知する必要のない,例えば『火のパーティクルから出た火の粉』のような孫階層のパーティクルなら,DrawAutoを活用するのは面白いかもしれない」とも述べており,将来的に同機能を採用する可能性に含みを持たせている。
●テクスチャレベルのシミュレーション
さてもう一つ,テクスチャレベルのシミュレーションは主に,水面における波の動きを生成するために用いられている。「テクスチャがなんで波の動きになるの?」という疑問が浮上するかもしれないので,少し確認しておこう。
そもそも「テクスチャ」と聞くと画像のイメージを持ちやすいが,プログラマブルシェーダ時代においては,PCにおけるメインメモリというか,配列データの格納場所として活用されることが多い。それこそ「水面の立体的な凹凸」としての波を生成するときには,複数のテクスチャを「シミュレーション用のワークバッファ(作業用記憶領域)」として活用するのだ。
水面を表現する場合は,テクスチャに波の凹凸情報などが格納(=記録)される。そしてピクセルシェーダ(として起用されたストリーミングプロセッサ)は,このテクスチャに対して波動シミュレーションを適用し,次の水面の凹凸状態を算出。その結果を基に,後のパスで当該テクスチャに記録された凹凸情報を実際の水面ポリゴン上の頂点に適用して摂動(※力学用語で,多方向かつさまざまな大きさのベクトルが混ざった動きのこと)させ,ジオメトリレベルでの凹凸に変換するのである。
GPUに詳しい読者のなかにはピンときた人も多いだろうが,これは,テクスチャ情報をもとに頂点情報を変調する,頂点テクスチャリング(Vertex Texture Fetching,以下VTF)の処理だ。DirectX 9時代はNVIDIAのGPUにしか実装されなかったVTFだが,統合型シェーダ(Unified Shader)アーキテクチャが当たり前のDirectX 10世代では,すべてのGPUが対応している。だから,DirectX 10専用の3DMark Vantageは積極的に活用しても問題がないというわけ。
なお,3DMark Vantageにおけるテクスチャレベルのシミュレーションでは,PCの性能にかかわらず一定の内容が実行される。つまり,高速なPCなら短時間で,低速ならより時間をかけて処理されるという違いはあるが,実行されるシミュレーションの過程も結果も同じ(※というか,変わってしまったらベンチマークテストにならない)ということだ。
また,布や水面など一部のシミュレーションでは,当該シーンをレンダリングした後の深度値(=Zバッファの内容)を参照することで,シミュレーション対象物とシーン内の動的オブジェクトの衝突判定を行い,オブジェクトの挙動を再現(あるいは表現)しているという。
3DMark Vantageの影生成法は,「3DMark06」と同型の「デプスシャドウ」(Depth Map Shadow)技法が採用された。影の生成元の光源位置からZバッファレンダリングを行って,光源からの奥行き情報(深度情報)を「シャドウマップ」(Shadow Maps)として生成し,視点からのシーンをレンダリングするときには,「視点からのシーンの奥行き情報とシャドウマップを吟味して影か否かの判断をしつつ,各ピクセルについてライティングを行う」影生成技法になる。実在の3Dゲームにおいても影生成の主流はデプスシャドウ技法になっているため,この選択は妥当といえるだろう。
ちなみに本技法は「シーンの遮蔽構造であるシャドウマップを生成する」という技法的特徴から「シャドウマップ」技法と呼ばれることもある。3DMark Vantageでは,通常シーンのレンダリングの前に,このシャドウマップ生成を行っているという。
さて,デプスシャドウ技法では,そのシーンに対する光の遮蔽構造をシャドウマップが把握することになるため,セルフシャドウや相互投射影などといったあらゆる影生成を行えるのだが,シャドウマップ解像度を高く取っておかないと,生成した影にエイリアシング(=ジャギー)が強く出るという弱点も併せ持っている。この弱点を克服するためにさまざまな改良版技法が考案されつつあるというのが,3DMark Vantageのリリースされた今日(こんにち)の状況だ。
3DMark Vantageでは,このデプスシャドウ技法の改良版である二つの技法が実装されている。一つは「近傍フィルタ処理付きカスケード・シャドウマップ」,もう一つは「バリアンス・シャドウマップ」だ。
●近傍フィルタ処理付きカスケード・シャドウマップ
近傍フィルタ処理付きカスケード・シャドウマップ(Percent Closer Filtering on Cascaded Shadow Maps。以下,PCF付きカスケード・シャドウマップ)は3DMark06で採用された技法で,3DMark Vantageでもほぼ同じものが実装されている。PCF付きカスケード・シャドウマップについては,筆者連載のバックナンバー「3DMark06の秘密 第2回『3DMark06で学ぶ影生成事情』」で詳しく解説しているので,興味を持った人はそちらを参考にしてほしい。
余談だが,PCF付きカスケード・マップ技法はカプコンの「ロスト プラネット エクストリーム コンディション」にも採用されている。画像は同タイトルにおけるカスケード・シャドウマップのイメージ(※連載バックナンバー「カプコンに聞く『ロスト プラネット』のグラフィックスオプション」より再掲)
念のため簡単に説明しておくと,デプスシャドウ技法のように,シャドウ解像度を“ムダに”高くするのではなく,適当な解像度のシャドウマップを複数用意し,視点の近いところから遠いところまでの影生成をこれらでカバーするというテクニックになる。シャドウマップをカスケードさせて(≒段階的に配置して)レンダリングするカスケード・シャドウマップ技法というわけだ。
そして,シャドウマップを参照した「影か否か」の判定に当たって,判断対象点の周囲にある複数点をサンプルして処理するのがPCFになる。このPCF処理におけるサンプル数の大小は3DMark Vantageの設定オプション「OPTIONS」にある「SHADOW SHADER QUALITY」の「Entry / Performance / High / Extreme」から4段階に指定できることになっているが,各設定がそれぞれ何サンプルなのか,内訳は明らかにされていない。
●バリアンス・シャドウマップ
二つめの影生成技法となるバリアンス・シャドウマップ(Variance Shadow Maps。以下,VSM)は,Unreal Engine 3にも採用されている技法で,こちらは「Graphics Test 2: New Calico」で活用されている。
「シャドウマップを生成し,これを参照して『影か否か』を判断しながらシーンをレンダリングしていく」という大まかな流れはデプスシャドウ技法と同じ。しかし,デプスシャドウだとこの「影か否か」を「Yes」「No」の二値判定するのに対して,VSM技法では確率論で用いられる「チェビシェフの不等式」(Chebychev’s Inequalities)を用いて,「光が当たっている最大確率」を算出して行うのだ。
チェビシェフの不等式は,次のとおり表される。
P(x≧t)≦ | σ2 |
σ2+(t-E(x)) |
これは「分散σ2と平均値E(x)のデータがあるときに「x≧t」となる確率Pの最大値を求める」不等式だ。
デプスシャドウ技法において,「シャドウマップに記録されている値(=遮蔽物から光源までの距離)」>「レンダリングしようとしているピクセルから光源までの距離」となったときには光が当たっていると判断できる。つまり,求めたい確率「P(x≧t)」において,tを「レンダリングしようとしているピクセルから光源までの距離」としてこの不等式を活用すると,確率P(x≧t)は「光が当たっている確率」に相当するというわけである。
なお,分散σ2は以下のように表され,平均値E(x)はシャドウマップに記録されている値を用いて計算される。
σ2=E(x2)-E(x)2
確率は0〜1の範囲で表されるため,そのまま影の色(=影の濃さ)として利用できる。影の本体に近ければ近いほど影となる確率が高くなって影の色は濃くなり,逆に影の輪郭から遠くなればなるほど影の確率が下がって影の色は薄くなる。結果として,影の輪郭付近がグラデーションのようになり,ソフトシャドウ的な表現になるのだ。もちろん,物理的に正しいソフトシャドウではないが,“見た目的”には十分な妥当性がある。
3Dグラフィックスでは,そのピクセルを描画してもいいかどうかの判断に当たって,Zバッファに記録された深度値を参照する。Zバッファには最後に書き込まれた「ピクセルの視点から見た奥行き情報(=深度値)」が書き込まれていて,これから描画しようとするピクセルの深度値が,Zバッファ上の深度値より奥側ならば,「すでに描かれているピクセルのほうが視点から見える」ため破棄される。逆に,Zバッファ上の深度値よりも手前ならそのピクセルは描かれることになるわけだが,このときよく考えると,先に書き込まれていたピクセル(=新しいピクセルよりも奥側にあったピクセル)はムダになる。つまり,当該ピクセルのために費やされた計算時間はムダだったことになってしまう。
高度なピクセルシェーダプログラムを動かしていればいるほど,このムダな時間は重くのしかかってくる。最新のリアルタイム3Dグラフィックスでは,長大で複雑なピクセルシェーダプログラムを動かすことが多くなってきているため,「描いたピクセルが実はムダだった」というのは演算リソースの深刻なムダ遣いとなるのだ。
そもそもピクセル描画とZバッファ更新を同時にやっているからこういう無駄が起こる。ならばピクセルシェーダプログラムを動かさず(=ピクセル描画を行わず),先にそのシーンの最終的な深度情報を作り上げてしまい,その結果を用いれば,上書きされて無意味になってしまうピクセルの描画は行わずに,実際に有効となるピクセルのみについて複雑なピクセルシェーダプログラムを動かして描画できることになるではないか。
3DMark Vantageのエンジンでは,そんな「先行Zバッファレンダリング」のテクニックを実装している。
まあ,先行Zバッファレンダリング時も,後段となる通常レンダリング時も,ジオメトリなどの一部の計算処理は重複して行われることになってしまうので,まったくムダがないかというとそうでもないが,ピクセルシェーダ負荷のほうが明らかに高くなると予見できるグラフィックス設計では有効なメソッドだ。実際,最近の3Dゲームエンジンでも採用されつつある。
「不透明材質」というとなにやらイメージしにくいが,要するに,透けて見える透明/半透明な材質以外の通常のものをライティングするプロセスである。
3DMark Vantageでは,このライティングプロセスにおいて,最新トレンドに則ったハイダイナミックレンジ(High Dynamic Range。以下,HDR)レンダリングを実装している。各αRGBが16bit浮動小数点(FP16)のレンダーターゲットを採用しているとのことだ。3DMark06の頃からFP16-64bitバッファを活用していたので,劇的な進化があったわけではないが,逆に考えれば「3Dゲームグラフィックス用途のHDRレンダリングなら,FP16-64bitバッファのレンダーターゲットで必要十分である」とはいえるかもしれない。
キューブマップや環境マップテクスチャについてもHDRのFP16-64bitフォーマットを採用しており,HDR次元のレンダリング(=ライティング)が行えるようになっている。
デカールテクスチャ(=画像テクスチャ)などは各αRGBが8bitの32bitフォーマットを採用しているが,格納値はsRGB値から線形値に変換されているとのこと。詳しくは言及されていないが,HDRレンダリングパスと迎合させるために共通指数項やHDRスケール値をα値などに入れて,計算時には32bitバッファをFP16のHDR次元に変換するような仕組みを取り入れているのかもしれない。
透明/半透明材質のライティングは,3Dグラフィックスにおいて,一筋縄では行かない面倒なテーマだ。
基本的に透けて見えるので,深度値を使った「カリング」――前述した,描画不要なピクセルを破棄する処理――が役に立たない。そのため,不透明材質をレンダリングし終えてから行うことになっているのである。
3DMark Vantageでの透明/半透明材質は主に火花,煙,水しぶきなどのパーティクル関係が多いようだ。
パーティクルと不透明の通常材質シーンとの合成では,パーティクルと通常材質背景との境界線が露呈しないようにする「ソフトパーティクル」(Soft ParticleあるいはSoft Clipping)処理が行われている。これも,最近の3Dゲームグラフィックスでは採用が当たり前となりつつあるテクニックだ。本連載では「Call of Duty 2」のグラフィックスオプション解説時に取り扱ったことがあるが,最も基本的なのは「パーティクルのピクセル描画に当たって,当該シーンの深度値とピクセルの深度値を比較して,その交差線に向かって透明度を上げていく」手法である。
●3DMark Vantageにおけるシェーダの仕様
透明/半透明材質のライティングに関連して,3DMark Vantageに用いられているシェーダの仕様についても言及しておこう。
3DMark Vantageにおけるシェーダプログラムは大まかに三つのタイプ,材質シェーダ(Matreial Shader),ライティングシェーダ(Light Shader),座標変換シェーダ(Transformation Shader)に分かれるとFuturemarkは説明する。
材質シェーダは,衣服や岩,金属,肌,樹脂といった,表現する材質ごとの反射モデルをシェーダプログラム化したものに相当する。発光する材質もこの材質シェーダの類だ。
ライティングシェーダは,「材質シェーダが処理を行う対象ピクセルに,光源からの光がどのように注がれるのか」を処理するシェーダだ。現在のシェーダプログラムの仕様では,点光源,並行光源といったように光源の種類が変わったり,あるいは光源の数が変わったりしたときに,光源状況に応じたシェーダプログラムを用意しなければならない。この要請へ柔軟に対応するための仕様と思われる。
ジャケットにはフレネル反射付きのライティングが行われたり,眼球内には情景が映っていたりと,Jane Nashでは相応にリッチなシェーダが動いている様子。わざとらしいほどの透明感を持った彼女の肌には,もしかすると簡易的なスキンシェーダも実装されている? 深度値を活用して厚みを算出し,これを基に擬似的な表面下散乱シェーダを実現するのは,3DMark06の水棲怪物で実績があるだけに,何かやっているのかも?
座標変換シェーダは,主に頂点シェーダが行う座標系の変換処理を行うものになる。ボーン(=骨格)の変形により表皮ポリゴンがどのように変形するかの処理を行うスキニング処理なども,この座標変換シェーダの部類に属する。
3DMark Vantageのエンジンにおいて,材質シェーダとライティングシェーダはHLSL(High-Level Shader Language,上位レベルシェーダ言語)で書かれた断片ソース(=テキストベース)で管理されている。
そしてエンジンの実行開始時には,そのシーンで必要とされる材質シェーダ部品と,そのシーンで用いられる光源の種類と数に応じて適切なライティングシェーダ部品をかき集め,「1本の完成されたシェーダプログラムのテキストファイル」として合成する処理が行われる。つまり,エンジンが最初にシェーダプログラムのテキストファイルを調合しているわけだ。合成したシェーダプログラムはコンパイルされ,実行形態に変換される。テスト読み出し中の画面で,インジケータに「Creating Shaders」と表示されるが,これが,シェーダプログラムのテキストファイルを合成してコンパイルしているフェーズである。
シェーダプログラムはGPU側に転送されないと実行できないため,実際に3DMark Vantageデモシークエンスの描画が始まる前には,コンパイルされて生成されたシェーダコードをシステムキャッシュに読み込ませたり,GPUに転送したりするエンジンのウォームアップが行われる。
シェーダプログラムはDirectX 10/SM4.0なので,同種の光源が複数ある場合は,その光源の分だけループして,材質シェーダのサブルーチンをコールする。異なる種類の光源が複数ある場合は,適切なライティングシェーダと材質シェーダを組み合わせて1本の長いシェーダプログラムとして構成し,シングルパスとして実行する。
実質的に,シェーダプログラム長の制限がなくなったDirectX 10/SM4.0の特性を活用したエンジン/シェーダ設計がなされているわけだ。テストされるGPUの立場から見れば,ループ実行や長いシェーダプログラムの実行を試されることになる。
- 関連タイトル:
3DMark Vantage
- この記事のURL:
COPYRIGHT(C)2008 FUTUREMARK CORPORATION