(あかん)

OpenGLで作るiPhone SDKゲームプログラミング - 6章

レースゲーム(3D)

6-4 頂点バッファオブジェクト

こはちょっと酷い。
執筆者はもう疲れきってしまっています。
一刻も早く本を書き終えたくてしょうがない様子です。
VBOはOpenGLにおいて重要な技術であるはずなのに、ろくに説明されていません。

仕方がないので、ここはVBOの基本的な使い方を別書から学ぶことにしました。
iPhone 3D プログラミング P94より」
ざっと読んで理解した内容によるVBO使用手順。

①バッファハンドル用の変数を用意しておく

GLuint buffer;

②一時メモリ内に座標配列を作成する
今までと同じように、x, y, z, x, y, z...の一次元配列を作成する。
作成した座標配列の先頭へのポインタを、ここではverticesと仮定する。
テクスチャマッピング座標配列の先頭へのポインタを、coordsと仮定する。
頂点の色はglColor4ubで一括指定することとする。


③頂点バッファを作成する

glGenBuffers(1, &buffer);

④頂点バッファをバインドする

glBindBuffer(GL_ARRAY_BUFFER, buffer);

第一引数は、頂点インデックスを指定するか、頂点座標を指定するか、のどちらか。ここでは頂点座標を指定することとする。


⑤頂点データをビデオメモリに転送する
方法は2つ。
glBufferDataを使うか、glBufferSubDataを使う。
この2つの関数の違いは、glBufferSubDataは、既に作成されたVBOの「更新」にだけ使うという点である。

ここでは、頂点座標とテクスチャマッピング座標を連続するメモリに取っているわけではなく、

GLfloat* vertices;   // 頂点座標
GLfloat* coords;     // テクスチャマッピング座標

という別々のメモリアドレスとして持っていると想定する。

このような場合は、最初にglBufferDataでデータを転送した後、glBufferSubDataで追加のデータを転送する。

・verticesの要素数をvnとする
・coordsの要素数をcnとする

glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vn, vertices, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vn, sizeof(GLfloat) * cn, coords);

-- ここまで、初期化時にやること --


⑥VBOを描画する
-- 毎フレームやること --

glBindBuffer(GL_ARRAY_BUFFER, buffer);       // VBOをバインドする

glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

// VBOの先頭アドレスを頂点座標の開始位置に指定する
glVertexPointer(3, GL_FLOAT, 0, 0);
glColor4ub(255, 255, 255, 255);
// VBOのテクスチャマッピングデータの開始位置を設定する
glTexCoordPointer(2, GL_FLOAT, 0, (GLfloat*)(sizeof(GLfloat) * vn));

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);

glDrawArrays(GL_TRIANGLES, 0, pCount/* ポリゴン数 */);

glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);         // VBOのバインドを解除する

注意しなければならないのは、VBOがバインドされている場合は、glVertexPointer, glColorPointer, glTexCoordPointerの引数の意味が変わることである。
VBOを使用しない場合は、座標のアドレスを渡していたが、
VBOを使用した場合は、バイトオフセットを指定することになる。


⑦VBOを解放する
-- VBOが不要になったときにやること --

glDeleteBuffers(1, &_vBuffer);


これを応用して、ごりごりと頂点座標を計算して、座標をVRAMに転送した上で、上記のように描画を行ったところ、八角柱のタイヤバリアが出来上がりました。