3Dゲームファンのためのグラフィックス講座
西川善司の3Dゲームファンのための「GRAVITY DAZE」グラフィックス講座(後編)
PowerVR系アーキテクチャの限界を超えた先に実現した「バンデシネ」スタイルグラフィックスの妙技
(2013/2/13 00:00)
前編では、PS Vitaに特化したグラフィックスプログラミング寄りの話題をお届けしたが、後編では、「GRAVITY DAZE」のビジュアルテイストを特徴付けているグラフィックステクニックを中心に見ていくことにしよう。
「GRAVITY DAZE」の特徴的なシェーディングの秘密(1)~ただのトゥーンシェーダーじゃないバンデシネシェーダーとは何か
「GRAVITY DAZE」は、アートコンセプトとして、「フレンチコミックの『バンデシネ』を目指す」ということが目標に設定された。このコンセプトを実現するために「GRAVITY DAZE」では、非常に特徴的なレンダリング手法、シェーディング手法を模索することになる。
方針として定まったのは、背景オブジェクト達は、リアル系のライティング&シェーディングを適用し、キャラクターモデル達に対しては、目標とされた「バンデシネ」タッチを実現するための「特別なシェーダー」を適用することだった。
その「特別なシェーダ」は試行錯誤の上完成する。便宜上、本稿では「バンデシネシェーダー」と呼ぶことにするが、実際には幾つかのシェーディングテクニックの複合技で実現されているものである。
基本となる部分は、イメージ的にはトゥーンシェーダーに近いもので、オーソドックスなLambert法による拡散反射のライティング計算をして、その明るさを3階調に分断するような仕組みになっている。各階調の明るさ境界はアーティストが設定したものになっており、3階調の各境界は滑らかなグラデーションになるようにブレンドを行なっている この処理の擬似コードを開発チームより頂いたので、下に示しておこう。
「GRAVITY DAZE」のトゥーンシェーダー(バンデシネシェーダー基礎部分) |
---|
// キャラ用フラグメントシェーダの要点部分だけを抽出した擬似コード // 頂点シェーダからの入力バッファや、ユニフォームバッファなどの宣言は割愛 // ライトの影響を計算する // ディレクショナルライト・ポイントライト・アンビエントライト・カメラライト(カメラ側から当てる光)の影響を受ける。 float light = CalcDiffuseLight(dirLight, shadowMap, position, normal, ambientLight, pointLights ...etc ); // 最も明るい色の中間色とのブレンド率を計算する. // borderDifAmbH/Lはアーティストにより設定されたボーダーラインの値. float diffuseAmbientBlend = smoothstep(borderDifAmbL, borderDifAmbH, light); // 中間色と影色とのブレンド率を計算する. // borderAmbShaH/Lはアーティストにより設定されたボーダーラインの値. float ambientShadowBlend = smoothstep(borderAmbShaL, borderAmbShaH, light); // ブレンド率を基にブレンドする. // diffuseColor, ambientColor, shadowColorはアーティストが設定した固定色. float3 color = albedoTextureColor * lerp(diffuseColor, ambientColor, diffuseAmbientBlend ); float3 color = lerp(color, shadowColor, ambientShadowBlend ); |
山口由晃氏:このままだとただのトゥーンシェーダーですが、我々が目指したのはフレンチコミックのバンデシネスタイルです。バンデシネでは、色の塗り分け方こそトゥーンシェーダー的ですが、ボリューム感、絵画的なタッチ感、ディテール感が乗るんです。なので、これを再現するために各キャラクターに対し、特別なライトを追加で焚いています。我々はこれを「女優ライト」と呼んでいました(笑)。
この「女優ライト」とは、「物理的には正しくないかもしれないが、望んだ陰影が出るように意図的に追加の光源を適宜置く」という発想が、本連載「バーチャファイター5」編で紹介した「美人光源」とよく似ている。ちなみに、映画撮影でもこうした見映え重視の追加ライティングはよく行なわれる。
山口氏:女優ライトはカメラ(視点)方向から当てられています。平行光源のライティングのみだと光源の反対側が常に陰色になります。陰色の部分(3段階の一番暗い部分)はテクスチャ色との乗算ではなくアーティストが指定した色そのものが直接出るようになっており、光源の反対側からキャラクターを見た場合にはこの陰色でつぶれた状態、ディテールがなくなった状態になります。そのため、キャラクターにはカメラ方向から追加の光源(女優ライト)をあてるようにしています。陰色に青っぽい色を直接入れるということもこのキャラシェーディングの特徴1つです。
「塗り」はシンプルなのに「ディテール表現は豊か」という特徴的な「GRAVITY DAZE」のキャラクタービジュアルはこうしたライティング&シェーディングシステムによって実現されていたのだ。
「GRAVITY DAZE」の特徴的なシェーディングの秘密(2)~輪郭線の生成
フレンチコミック「バンデシネ」のテイストを目指した「GRAVITY DAZE」のグラフィックスにおいて、非常に大きな特徴となっている要素に輪郭線がある。
キャラクターや背景に対しリアルタイムに、まるでペンで引いたような線が描き込まれていく様は非常に絵画的だ。これは事前にテクスチャ等に描き込まれているものではなく、特殊なシェーダーによってリアルタイムに生成されている。
ただ、前もって言っておかなければならないのは、キャラクターに対する輪郭線生成と、背景に対する輪郭線生成はアプローチが異なっているという点だ。
まず、キャラクターモデルの輪郭線生成の方から。キャラクターモデルはバンデシネタッチでレンダリングして、キャラクターモデルの実体を描画しているというのは上で解説した通りだ。
これに続いて、キャラクターに対する輪郭線生成を行なうのだが、これは頂点シェーダで、そのキャラクターモデルを構成する各頂点をその法線方向に膨張させ、視線方向に向いていないポリゴン(裏面)のみを黒で描画することで実践される。そのキャラクターモデルを膨張させた分が、はみ出て黒く残り、それが輪郭線となるという寸法なのだ。
膨張させたキャラクターモデルのポリゴンのうち、視線方向に向いているもの(表面)を描かないのは、そのキャラクターモデルの実体を上書きしてしまわないためだ。欲しいのは「キャラクターモデルの実体」と「輪郭線」なので、原寸の実体モデルからはみ出た膨張モデルの裏面だけを黒で描くわけである。
なお、輪郭線描画の際にキャラクターモデルに与える膨張率を固定値にしてしまうと、視点からの遠近で生成される輪郭線の太さが変わってしまうので、そのキャラクターモデルの視点からの奥行き位置と視界画角の値を元にして膨張率を調整している。キャラクターモデルが近くにいようが遠くにいようが、その輪郭線の太さが変わらないのはこの調整の恩恵なのだ。
背景オブジェクトに対する輪郭線描画はこの膨張モデルによる手法は用いられていない。というのも、この膨張モデルの手法は2パスレンダリングとなり、ポリゴン数が膨大な背景オブジェクトを輪郭線描画のために二度描画することは負荷増大に繋がって得策でないと考えられたためだ。
横川裕氏:そこで、レンダリング結果に対してポストエフェクトを適用して輪郭線を生成しています。逆にキャラクターモデルに対して、このポストエフェクトによる輪郭線生成を行なわなかったのは、このポストエフェクトによる輪郭生成が若干ノイジーだからです。
背景オブジェクトをレンダリングする際、ピクセルシェーダーは、背景オブジェクトに対するライティング&シェーディングの計算をしてRGBにピクセル色を出力すると共に、一緒に視線ベクトルとそのピクセルの法線ベクトルの内積を計算してその結果をαチャネルに仕込んでレンダーターゲットに書き出すようにする。
後段のポストエフェクトの処理フェーズでは、レンダーターゲットのαチャネルに対して、画像処理において古くから活用されるエッジ強調フィルタの1つ「Sobelフィルタ」を適用してやるのだ。
視線ベクトルと、レンダリング対象ピクセルの法線ベクトル、その2つのベクトルが織りなす角度が小さいほど、その2つのベクトルの内積値は大きくなり、織りなす角度が大きいほど内積値は小さくなる。隣接する内積値同士の差分が大きい場所が輪郭線と見なせるため、これをSobelフィルタにて強調化して顕在化させてやるのだ。
異なる2つのアプローチで生成された輪郭線とはいえ、最終的な映像を見ても背景とキャラクターの輪郭線の出方には大きな違和感はなく、うまく一体化した形で見えている。
「GRAVITY DAZE」の特徴的なキャラクターシェーディングの秘密(3)~背景のトーンマッピング処理とトーンマッピングの影響を受けないキャラクターモデル
前編でも紹介したように、本作のメインレンダーターゲットは720×408ドットであり、フォーマットはαRGBが各16ビット浮動小数点(FP16)のHDR(HIGH DYNAMIC RANGE)レンダリングパイプラインが採用されている。ただし、HDRレンダリングが適用されているのは背景オブジェクト達のみで、キャラクターモデル達に対しては、HDRレンダリングではなく、ここまでで解説してきたような「バンデシネ」シェーダーが適用されている。
「GRAVITY DAZE」では、背景とキャラクターは、1つのレンダーターゲットに出力されているため、1つのレンダーターゲット内に異なるアプローチのライティング/シェーディングによる結果が混在することになるのだ。
背景はHDRレンダリングされているため、背景は低輝度な領域から超高輝度な領域までをFP16で表現できている。ただ、PS Vitaの有機ELディスプレイは、一般的なテレビやPCモニタと同じく、RGB各整数8ビット(int8)で表現される、いわゆるLDR(Low Dynamic Range)なディスプレイ装置なので、RGB各FP16で表現されたレンダーターゲットを直接表示することはできない。当たり前だ。
そこでLDR表現に変換する必要があるわけだが、そのメカニズムは特に「トーンマッピング」と呼ばれる。トーンマッピングは、HDRレンダーターゲットの下位ビットをただ切り捨てるような単純な減色処理よりも、HDRレンダリングされたレンダーターゲットの平均輝度を取得して、その平均輝度を基軸にして暗い階調と明るい階調をLDRに圧縮するような非線形減色を適用した方が見映えがリアルになるとされる。しかも、これをリアルタイムに実行すれば、まるでカメラの自動露出補正の効果や、あるいは眼球の瞳の絞り機構による暗順応(明→暗への順応)や明順応(暗→明への順応)が再現されたような効果までが得られる。
「GRAVITY DAZE」では、このトーンマッピングのアルゴリズムとしては、Erik Reinhard氏らがSIGGRAPH2002で発表した「Photographic Tone Reproduction for Digital Images」を採用している。これは、簡単に言うと、与えられたHDRフレームの平均輝度を対数次元で求め、この対数平均輝度を基準とし、暗部階調に対しては線形に近い階調を与え、一方、明部に行けば行くほど階調変化が鈍くなるような特性でLDRに変換するアルゴリズムになっている。物理的な正確性はさておき、かなり人間が普段見る情景に近くなることから、算術的なアプローチのトーンマッピング手法としては定番とされているテクニックだ。
「GRAVITY DAZE」では、この対数平均輝度の計算を、負荷低減のために、32×16テクセルにまで縮小した最終映像フレームに対して行っている。なお、この超縮小版の最終映像フレームは、後述するHDRレンダリング効果の1つである「ブルームエフェクト」にも用いるポストエフェクトのタネ映像生成用ワークバッファに作成される。
ただ、このトーンマッピング処理は、非HDRレンダリングされたバンデシネシェーダーベースのキャラクターモデルに対しては除外する必要がある。
そこで、「GRAVITY DAZE」では、そのフレームレンダリングの際にキャラクターモデルを描画する際に、メインレンダーターゲットと同解像度のステンシルバッファにも同時出力し、これをトーンマッピング処理時のマスクとして使って、描画されたキャラクターモデルに対してはトーンマッピング処理の影響が出ないようにしている。
松田氏:PS VitaのGPUでも、マスクパターンをステンシルバッファに出力した後、トーンマッピング処理時に直接そのマスク内容をピクセルシェーダで参照することができました。ただ、「参照できるできない」はステンシルバッファのフォーマットの種類によって違うようです。今作の開発では、読めそうなフォーマットにしたら、ちゃんと読めました(笑)
「GRAVITY DAZE」では、このユニークなトーンマッピングにより、適度な明るいシーンではキャラクターモデルが背景に馴染むことになり、やや暗いシーンではキャラクターモデルの存在感を際立たせることができており、本作ならではの特徴的なビジュアルテイストを実現できている。