OpenGL 3.3 と過ごした夏休み2013

日記サボってしまってごめんなさい!更新間隔をあけないようにします…(汗)

今年も残るところ3ヶ月ちょっとで終わります。このところ外も涼しくなってきました。 9月が終わっちゃう前に、夏の間にやってみたことを振り返ってみます。

OpenGL 3.3

今夏を一言で表すと残念なこと(?)に "OpenGL 3.3" で片づけられます。休みの日は 1 日中触っていました。 もともと趣味で作っていたゲームエンジンでは、グラフィックス API に Direct3D 11 を使用していました。 そんな中、ここ 1 年ほどモバイル向けの OpenGL ES を触る機会があったことと、OSX でゲームを動かしてみたいことも相まって OpenGL に手を出しました。

OpenGL のバージョンが 3.3 なのには理由があります。1 つは OpenGL 3.3 から導入された Sampler Object が利用できることです。Sampler Object が導入されたことで、テクスチャとサンプラーの分離ができます。Direct3D 11 ではテクスチャとサンプラーがそれぞれ独立していたので、それに合わせて Sampler Object を利用する必要がありました。 もう 1 つの理由は、OpenGL 3 からハードウェアインスタンシングがサポートされていることです。こちらも元々エンジンが Direct3D 11 のハードウェアインスタンシングをがんがん利用していたため、OpenGL でも実装する必要がありました。ちなみに OpenGL だと Geometry instancing と呼ぶ場合が多いようです。

ハードウェアインスタンシング(Hardware instancing)

パーティクルにしても、スプライトバッチにしてもインスタンシングは必要不可欠です。今回はキューブブロックを並べてます。

ハードウェアインスタンシング

Hardware instancing

ブロックをたくさん出してもフレームレート 60 fps をキープしています。 せっかくなのでワイヤーフレーム表示してみました。

Hardware instancing(wireframe)

もう何がなんだかわかりません(汗)

遅延シェーディング

Albedo

Deferred shading(Albedo)

World-space normal

Deferred shading(World-space normal)

Depth

Deferred shading(depth)

G-buffer (Geometry buffer) にそのままアルベドとワールド空間の法線と深度情報をそれぞれ書き出しています。特に工夫した点はなく、ピュアな遅延シェーディングです。G-buffer の内訳は次の通りです:

Format RGB A
RT0 R8G8B8A8(Unorm) Diffuse Albedo RGB None
RT1 R10G10B10A2 World-space normal XYZ None
RT2 R32(Float) Depth

K●LLZONE 2 です。 Specular intensity を RenderTarget 0 (RT0) で未使用だった Alpha に格納するのもよさそうです。(今回はスペキュラーマップを用意していませんでした。)

ライティングした結果が次です。

Half-lambert + Phong shading

ハーフランバート(Half-lambert) をベースにしたフォンシェーディングを行っています。このスクリーンショットだと鏡面反射がいまいちわかりにくいですね…(汗)。

バンプマッピング

バンプマッピングもしてみました。こちらはバンプマッピング後の G-buffer のノーマルマップの様子です。

Bump mapping(World space normal)

アルベドなしのフォンシェーディングです。鏡面反射光でギラギラしてます。

Bump mapping + Phong shading

被写界深度ブラー(Depth of field)

先ほどの最終イメージには、被写界深度ブラーをかけています。深度情報を使ってブラーをかけただけですが、スクリーンショットの見栄えがぐーんとよくなります。ゲームプレイ時は邪魔になりそうですが、スクリーンショット時はピンポンブラーにして強めにかけてもいいかもしれません。

エッジ検出(Edge detection)

ピクセルシェーダで G-buffer の法線・深度情報を使ってエッジ検出もしました。

Edge detection

トゥーンレンダリングと組み合わせたいですね~。フォンシェーディングと合わせてみたら、デコボコとテカリがエッジに重なっていまいちな結果になりました。

Edge detection + Phong shading

未解決のバグ

OpenGL での実装はほとんど終わっていますが、たちの悪いバグが 1 個あります(汗)。3 週間ずっと未解決のままです。なかなか原因がわからず、お手上げ状態です。エンジンの組み方に問題があるのは確かなようです。

バンプマッピングでは、アルベドマップと法線テクスチャの 2 つをシェーダの中でサンプリングします。また遅延シェーディングでは、書き込んだ G-buffer をサンプリングします。G-buffer は複数のテクスチャに過ぎません。こういった「マルチテクスチャ」はごく当たり前のように使うことになります。エンジンに潜んでいるバグは、この「マルチテクスチャ」が特定の条件で使えないというものです。先に挙げたバンプマッピングの場合、テクスチャユニット0 にセットされたテクスチャ(アルベドテクスチャ)以外をサンプリングできません。テクスチャユニット1 にセットされたテクスチャ(法線マップ)ではなく、テクスチャユニット0 のアルベドテクスチャをサンプリングしてしまいます。単純なマルチテクスチャや、遅延シェーディングの場合、問題なくサンプリングできています。Hardware instancing + 遅延シェーディング + バンプマッピングの場合、G-buffer 書き込み時のみなぜかマルチテクスチャが上手くできないようです。早いところ原因をつかみたいです。

秋からやること

半月以上かけてもバグの原因がわからないとなると、非常に飽きてしまい、プログラムを書いていても面白くないものです。そこで、OpenGL からいったん離れて、再び Direct3D に戻ることにしました。ちょうど区切りもいいので OpenGL で動かすのはいったん後回しにします。兎にも角にも今作っているゲームをがんがん作っていきます。マルチテクスチャのバグはその後で暇を見つけて原因を探すことにします。グッバイ OpenGL。

日記を始めた理由の 1 つに、実装したことと次にやることを書くことで、いろいろな誘惑を振り切ってゲームの完成が遠のかないようにする、という目的がありました。…が、そんな当初の目的もすっかり忘れていました(汗)

実装がんばるよー!!

Leave a Reply