4

Vertex Buffer Objects (VBO) を使用して、iPhone 用の Open GL ES 1.1 ゲームでやや複雑なモデルのレンダリングを改善したいと考えています。SO に関するいくつかの投稿とこの (http://playcontrol.net/ewing/jibberjabber/opengl_vertex_buffer_object.html) チュートリアルを読んだ後でも、VBO の理解と、Cheetah 3D エクスポート モデル形式での VBO の実装方法を理解するのにまだ問題があります。誰かが VBO を実装し、それを使用して指定されたデータ構造で頂点を描画し、構文を説明する例を教えてください。どんな助けでも大歓迎です!

#define body_vertexcount    434
#define body_polygoncount   780

// The vertex data is saved in the following format:
// u0,v0,normalx0,normaly0,normalz0,x0,y0,z0
float body_vertex[body_vertexcount][8]={
{0.03333, 0.00000, -0.68652, -0.51763, 0.51063, 0.40972, -0.25028, -1.31418},
{...},
{...}
}

GLushort body_index[body_polygoncount][3]={
{0, 1, 2},
{2, 3, 0}
}

Pro OpenGL ES (Apppress) の第 9 章の助けを借りて、次のコードを作成しました。DrawElements コマンドで EXC_BAD_ACCESS を取得していますが、その理由がわかりません。誰かが光を当ててくれませんか?ありがとう -

// First thing we do is create / setup the index buffer
glGenBuffers(1, &bodyIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bodyIBO);

// For constrast, instead of glBufferSubData and glMapBuffer, 
// we can directly supply the data in one-shot
glBufferData(GL_ELEMENT_ARRAY_BUFFER, body_polygoncount*sizeof(GLubyte), body_index, GL_STATIC_DRAW);

// Define our data structure
int numXYZElements = 3;
int numNormalElements = 3;
int numTextureCoordElements = 2;
long totalXYZBytes;
long totalNormalBytes;
long totalTexCoordinateBytes;
int numBytesPerVertex;

// Allocate a new buffer
glGenBuffers(1, &bodyVBO);

// Bind the buffer object to use
glBindBuffer(GL_ARRAY_BUFFER, bodyVBO);

// Tally up the size of the data components
numBytesPerVertex = numXYZElements;
numBytesPerVertex += numNormalElements;
numBytesPerVertex += numTextureCoordElements;
numBytesPerVertex *= sizeof(GLfloat);

// Actually allocate memory on the GPU ( Data is static here )
glBufferData(GL_ARRAY_BUFFER, numBytesPerVertex * body_vertexcount, 0, GL_STATIC_DRAW);

// Upload data to the cache ( memory mapping )
GLubyte *vboBuffer = (GLubyte *)glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);

// Caclulate the total number of bytes for each data type
totalXYZBytes = numXYZElements * body_vertexcount * sizeof(GLfloat);
totalNormalBytes = numNormalElements * body_vertexcount * sizeof(GLfloat);
totalTexCoordinateBytes = numTextureCoordElements * body_vertexcount * sizeof(GLfloat);

// Set the total bytes property for the body
self.bodyTotalBytes = totalXYZBytes + totalNormalBytes + totalTexCoordinateBytes;

// Setup the copy of the buffer(s) using memcpy()
memcpy(vboBuffer, body_vertex, self.bodyTotalBytes);

// Perform the actual copy
glUnmapBufferOES(GL_ARRAY_BUFFER);

例外が発生している描画コマンドは次のとおりです。

    // Activate the VBOs to draw
    glBindBuffer(GL_ARRAY_BUFFER, bodyVBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bodyIBO);

    // Setup drawing
    glMatrixMode(GL_MODELVIEW);
    glEnable(GL_TEXTURE_2D);
    glClientActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D,lightGreyInt);

    // Setup pointers
    glVertexPointer(3, GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 0 );
    glTexCoordPointer(2, GL_FLOAT, sizeof(vertexStruct),  (char *)NULL + 12 );
    glNormalPointer(GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 24 );

    // Now draw the body
    glDrawElements(GL_TRIANGLES, body_polygoncount,GL_UNSIGNED_SHORT, (GLvoid*)((char*)NULL));
    //glDrawElements(GL_TRIANGLES, body_polygoncount, GL_UNSIGNED_SHORT, nil);
    //glDrawElements(GL_TRIANGLES,body_polygoncount*3,GL_UNSIGNED_SHORT,body_index);
4

1 に答える 1

3

まず、インデックス バッファが小さすぎます。body_polygoncountインデックスだけではなく、 body_polygoncount * 3. また、あなたはタイプを台無しにしましたGLushort.GLubyte

glBufferData(GL_ELEMENT_ARRAY_BUFFER, body_polygoncount*3*sizeof(GLushort),
             body_index, GL_STATIC_DRAW);

そして、データには最初にテクスチャ座標が含まれ、次に法線、次に各頂点の位置が含まれているため、属性のオフセットを台無しにしました。

glVertexPointer(3, GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 20 );   //3rd, after 5*4 byte
glTexCoordPointer(2, GL_FLOAT, sizeof(vertexStruct),  (char *)NULL + 0 ); //1st
glNormalPointer(GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 8 );       //2nd, after 2*4 bytes

そして最後に、glDrawElements呼び出しでは、三角形の数ではなく、要素 (インデックス) の数を指定するため、次のようにする必要があります。

glDrawElements(GL_TRIANGLES, body_polygoncount*3,
               GL_UNSIGNED_SHORT, (GLvoid*)((char*)NULL));

そうでなければ、あなたのコードは合理的に見えます (もちろん、マッピングは無意味で、glBufferDataもう一度使用することもできましたが、学習のために行ったと思います)。

しかし、VBO を使用せずにクライアント側の頂点配列を使用しただけで、OpenGL ES 1.1 には即時モードがないと思っていた場合にも、これらすべてのエラーが発生したのではないかと思いますglBegin/glEnd。これらのエラーを認識していない場合、以前は VBO なしでゲームが動作していたのはなぜでしょうか。

于 2012-03-18T23:43:47.197 に答える