2012-03-17 6 views
4

Я хотел бы использовать Vertex Buffer Objects (VBOs) для улучшения моего рендеринга нескольких сложных моделей в моей игре Open GL ES 1.1 для iPhone. После прочтения нескольких сообщений в SO и этого учебника (http://playcontrol.net/ewing/jibberjabber/opengl_vertex_buffer_object.html), мне все еще не удается понять VBOs и как их реализовать, учитывая мой формат модели экспорта Cheetah 3D. Может ли кто-нибудь, пожалуйста, привести пример внедрения VBO и использовать его для рисования моих вершин с данной структурой данных и объяснения синтаксиса? Я очень благодарен за любую помощь!iPhone Cheetah 3D OpenGL ES Vertex Buffer Object (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} 
} 

Я написал следующий код с помощью главы 9 из Pro OpenGL ES (Appress). Я получаю EXC_BAD_ACCESS с помощью команды DrawElements, и я не уверен, почему. Может ли кто-нибудь пролить свет? Спасибо -

// 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); 
+0

Я не могу поверить, что не существует учебного ресурса, который объясняет вам это довольно хорошо, если вы уже знаете, как работают массивы вершин и остальная часть OpenGL (о чем говорится в ** вашей ** игре OpenGL ES 1.1). Вы также можете посмотреть [здесь] (http://www.songho.ca/opengl/gl_vbo.html), но связанный учебник из вашего вопроса выглядит разумным (я только просматривал его, хотя). –

+0

С чем вы столкнулись? Мы не собираемся писать код для вас. Как насчет структуры данных и синтаксиса, вы не понимаете? Просто будьте как можно более ясны, чтобы мы могли сформулировать разумный ответ. – user1118321

+0

Я вставил свой код, мне особенно не удается воспроизвести чередующиеся данные с вызовом glDrawElements. Я получаю EXC_BAD_ACCESS, я очень благодарен за помощь - – PhilBot

ответ

3

Ну, прежде всего указательных буферов слишком мал, вы не просто body_polygoncount индексов, но body_polygoncount * 3. Вы также перепутались типа, так как они трусы, вам нужно GLushort и не GLubyte, поэтому она должна быть

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

И потом, вы испортили корректоры ваших атрибутов, так как данные содержат первые текстуры Coords, то нормальная и тогда положение для каждой вершины, она должна быть

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 еще раз, но я думаю, вы сделали это для обучения), и если вы поняли все, что он делает, нет ничего более.

Но мне интересно, что все эти ошибки произошли бы, если бы вы использовали только вершинные массивы клиентской стороны без VBOs, и я думал, что OpenGL ES 1.1 не имеет немедленного режима glBegin/glEnd. Поэтому мне интересно, почему ваша игра работала ранее без VBOs, если вы не знаете об этих ошибках.

+0

Спасибо - я вижу свои ошибки .. теперь это имеет смысл.Я ранее рисовал, как: // Рисуем пистолет-рендеринг и текстуру для gunX // glBindTexture (GL_TEXTURE_2D, lightGreyInt); glVertexPointer (3, GL_FLOAT, sizeof (vertexStruct) и интерполяцияVerticesGun [0] [5]); glTexCoordPointer (2, GL_FLOAT, sizeof (vertexStruct) и интерполяцияVerticesGun [0] [0]); glNormalPointer (GL_FLOAT, sizeof (vertexStruct) и интерполяцияVerticesGun [0] [2]); glDrawElements (GL_TRIANGLES, gun2_polygoncount * 3, GL_UNSIGNED_SHORT, gun2_index); – PhilBot