3D Graphics API3DCGゲーム開発

OpenGLの癖を制する

3,4年ほど前にOpenGLESネイティブでゲームをフルスクラッチ開発しました。それまでOpenGLがどのようなものかは大体分かっていましたが、実際にコーディングした経験はありませんでした。
当時でDirectXの開発経験が15年ほどあったので、ほぼ何も勉強せずにOpenGLをコーディングできました。びっくりするくらいそのままDirect3Dの知識が通用し、APIの仕様すら(機能や引数すらも)何も見なくても、インテリセンスの助けもあり、そのまま感覚で打ち込めたのは驚きでした。

そもそもAPI(とか言語とか)は人が使い易いように作られているもの(使い易い環境を提供するのがAPIや言語の目的)ですから、根底をマスターしていれば新しいAPIでもすぐに使えます。
またDirect3DとOpenGLのあまりにもそっくりな構造には驚き、同時に安堵しました。2つともビデオカードと密接に関係しているAPIなのでそっくりになるのは当然なのでしょうけど、
それでも、OpenGLを全く触ったことがなかったので、やる前は不安でした。
あと、行列と3D系が”完全に逆”なのもスムーズなコーディングにとって大きな助けになりました。一部が同じで一部が異なるよりも”全く違って”くれたほうがやりやすいです。
行列を作るとき、Direct3Dと完全に逆と分かっていれば逆に作ればいいし、ベクトルと掛けるときも順番を逆にすればいい、また、3D系が左手右手で逆なのが分かっているのでZをマイナスにすればいいなど。全てが逆という潔さ(?)なので、何かを考えるときいちいち「あれD3DはこうだったけどOGLではどうなんだろう?」とGoogle検索する必要もなくなります。D3Dの逆を考えればいいだけです。

1年ほどまえから本格的に複数の他社OpenGL案件が入ったので、またOpenGLのコーディングを始め、現在2年目に突入しました。

昨日、ある機能の実装で2,3時間引っ掛かっていたのですが、あることに気付き一瞬で解決。そのある事がかなり大事、いやそれこそがDirect3DとOpenGLの大きな違いだと思い、自分自身が忘れないように、また、公開して世の開発者の大きな道標になればと思い、ここに記します。

OpenGLを始めてすぐに分かる(というかすぐ理解する必要がある)ことではあるのですが、OpenGL制覇の鍵は、

「コードの順番」 と 「見えないコード」

です。

私はこれをOpenGLの癖と呼んでいます。癖を制せばOGLを制す。

例えば、ある入れ物にデータを詰め込む場合

(1) D3Dの場合

データを用意。

D3Dの入れ物を作る。

入れ物にデータを入れる。

(2) OGLの場合

データを用意。

OGLの入れ物を作る。

OGLの入れ物に「これからいろいろやるからね~」と知らせる。

データを入れる。どこに入れるか指定しなくても上記入れ物に入る。

D3Dでは明示的に入れ物にデータを入れるコードになるので納得できるのですが、OGLの場合は、”入れる”というコードだけになるので最初は戸惑い不安になります。

もうちょっと具体的なほうが分かりやすいでしょうか。

(1) D3Dの場合

頂点データ data[1000] を用意

D3DBufferを用意

D3DBuffer->SetData(data)

(2) OGLの場合

頂点データ data[1000] を用意 ここは同じ

OGLBufferを用意 ここも同じ

Bind(OGLBuffer)  これが癖。「これからOGLBufferにいろいろやるからね」 という意味で、これ以降の処理はOGLBufferになされる

SetData(data) これが最初気持ち悪かった。どこにセットしてるの?みたいな。 直前(上)でBindした対象に対して処理される

 

「これからいろいろやるからね~」と知らせる これこそがOGLの癖(と私は呼んでいます)。D3Dとは決定的に異なる手順です。
D3Dの場合は、明示的に「どこに対して行っているのか」が見えるのですが、OGLの場合は、コードのある地点でBindした対象に対してそれ以降の処理が影響するということになります。

バッファーにかぎずテクスチャーやシェーダーなども同様です。
見えているコードの裏側にもうひとつの流れのコードを想像しながらコーディングしなくてはなりません。

もっとも、一旦その仕組みが分かってしまえばどうとうことはないので、是非参考にしてください。

で、昨日はまった問題ですが、NDAにより詳細は書けませんが、

こういうことです。

頂点データ data[1000] を用意

OGLBufferを用意

SetData(data) これを先に書いていた。

Bind(OGLBuffer)

SetDataを先に書いていたので、どう頑張ってもOGLBufferには入らないというわけです。癖に気付きハッと思いコードの順番を変えたらあっさり上手くいき、やったというより、げんなりです。

今回はここまで、それでは!

 

 

 

 

 

 

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です