最終更新: mikk_ni3_92 2008年09月09日(火) 17:07:14履歴
現在地 >> メニュー >> 基本編10 >> VertexBufferObject
関連:VertexBufferObject(part2)、VertexBufferObject(part3)、PixelBufferObject、FrameBufferObject
VBOの作成で行うのは、[発生]、[バインド]、[データのコピー]である。
[例]:VBOの作成
最後の引数は、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」とかで使う。
描画は頂点配列の時とほぼ同じ。ただし、データ元の引数は0にし、バインドを忘れずに。
ディスプレイリストは1度コンパイルすると、変更ができなかった。
しかし、VBOは可能。
方法は
クライアント側のメモリにVBOをマッピングできる時、返り値としてそのバッファのアドレスを返す。
※注意点
GPU側が動いている時は、glMapBufferARB()はGPUの処理が終わるまでreturnしない。
従って、glBufferDataARB()をNULLポインタでよんでから使う方がよいかもしれない。
(過去のデータは捨てられ、glMapBufferARB()がすぐに新しいポインタを返してくれる)
VBOを変更したら、クライアント側のメモリからマッピングをはずす。
関連:VertexBufferObject(part2)、VertexBufferObject(part3)、PixelBufferObject、FrameBufferObject
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"; }
最後の引数は、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」とかで使う。
描画は頂点配列の時とほぼ同じ。ただし、データ元の引数は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);
ディスプレイリストは1度コンパイルすると、変更ができなかった。
しかし、VBOは可能。
方法は
- glBufferDataARB()などでVBOに再コピー
- glMapBufferARB()を使う
クライアント側のメモリにVBOをマッピングできる時、返り値としてそのバッファのアドレスを返す。
※注意点
GPU側が動いている時は、glMapBufferARB()はGPUの処理が終わるまでreturnしない。
従って、glBufferDataARB()をNULLポインタでよんでから使う方がよいかもしれない。
(過去のデータは捨てられ、glMapBufferARB()がすぐに新しいポインタを返してくれる)
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); }