現在地 >> メニュー >> 基本編10 >> VertexBufferObject
関連VertexBufferObject(part2)VertexBufferObject(part3)PixelBufferObjectFrameBufferObject

VBO


VBOは、
頂点配列のように扱う事ができ、
ディスプレイリストのように命令をメモリにためる事ができる。

手順

  1. VBOを作成
  2. VBOを描画
  3. VBOをアップデートする


[1].VBOを作成


VBOの作成で行うのは、[発生]、[バインド]、[データのコピー]である。


[例]:VBOの作成
	GLuint VboId = 0;
	glGenBuffersARB(1, &VboId);   //発生
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, VboId); //バインド
	
	//データをVBOにコピー
	glBufferDataARB(GL_ARRAY_BUFFER_ARB, 3*3*sizeof(float), points, GL_STATIC_DRAW);

	//例外チェック(VBOと配列のサイズがあっているか?)
	int bufferSize = 0;
	glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &bufferSize);
	if(3*3*sizeof(float) != bufferSize){//一致していない場合
		glDeleteBuffersARB(1, &VboId);
		VboId = 0;
		std::cout << "Can't Create VBO\n";
	}

メモ


もし「glDrawElements()関数」や「glDrawRangeElements()関数」を使う場合は
「GL_ELEMENT_ARRAY_BUFFER_ARB」を指定する。

glBufferDataARB()関数


最後の引数は、9種類あるが、
Static:VBO上のデータが変更されない場合。
dynamic:VBO上のデータが変更される場合。(つまり、頻繁に繰り返し使われる場合)
stream:フレーム毎に変更される場合。(つまり、一度だけ使われる場合)

Draw:描画のためにGPU上に転送される。
read:クライアント側によって読み込まれる。
copy:Drawとreadの両方が使われる。


このフラグをみて、VBOはふさわしいと思われるところにメモリを用意する。
例えば、「GL_STATIC_DRAW_ARB」や「GL_STREAM_DRAW_ARB」はGPUを使う(はず)。

※VBOではデータを読み出すことはないので、「Draw」のみ。他は「PBO」とかで使う。


[2].VBOを描画する


描画は頂点配列の時とほぼ同じ。ただし、データ元の引数は0にし、バインドを忘れずに。
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VboId[0]);  //バインド
glEnableClientState(GL_VERTEX_ARRAY);  //

glVertexPointer(3, GL_FLOAT, 0, 0);  //最後の引数は「0」を指定
glDrawArrays(GL_TRIANGLES , 0 , 3);  //同じ

glDisableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

[3].VBOをアップデートする


ディスプレイリストは1度コンパイルすると、変更ができなかった。
しかし、VBOは可能。

方法は
  • glBufferDataARB()などでVBOに再コピー
  • glMapBufferARB()を使う
といった方法がある。

glMapBufferARB()関数


クライアント側のメモリにVBOをマッピングできる時、返り値としてそのバッファのアドレスを返す。

※注意点
GPU側が動いている時は、glMapBufferARB()はGPUの処理が終わるまでreturnしない。
従って、glBufferDataARB()をNULLポインタでよんでから使う方がよいかもしれない。
(過去のデータは捨てられ、glMapBufferARB()がすぐに新しいポインタを返してくれる)

glUnmapBufferARB()関数


VBOを変更したら、クライアント側のメモリからマッピングをはずす。

glBindBufferARB(GL_ARRAY_BUFFER_ARB, VboId[0]);
float *ptr = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB);
if(ptr)
{	
	ptr[2] = sin(angle); //1つ目の頂点、z座標を動かす
	angle += 0.1;
	if(angle > 360) angle = 0;
	glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
}

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






▲よろしければ広告のクリックもお願いします


▲ランキングに参加しました

管理人/副管理人のみ編集できます