Рисование с использованием объектов Vertex Buffer в OpenGL ES 1.1 не работает - PullRequest
2 голосов
/ 06 января 2012

У меня работает код OpenGL, но я пытаюсь немного улучшить его производительность (хотелось бы немного увеличить частоту кадров на старых устройствах). Я пытаюсь сделать это, используя объект буфера вершины.

Все, что делает мой код, это рисует серию из 360 GL_TRIANGLES, к которым применена текстура. Я переплетаю координаты и координаты текстуры в структуру данных.

typedef struct {
    GLfloat vertex[2];
    GLfloat texture[2];
    GLfloat padding[4];
} TextureVertex2D;

typedef struct {
    TextureVertex2D textureVertex[3];
} TextureTriangle2D;

Вот соответствующая часть моей инициализации

textureTriangles = (TextureTriangle2D*)malloc(360 * sizeof(TextureTriangle2D));

glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);

// This section is the only new code introduced for the VBOs.
glGenBuffers(1, &buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(TextureTriangle2D)*360, textureTriangles[0].textureVertex[0].vertex, GL_DYNAMIC_DRAW);
// end new code    

glVertexPointer(2, GL_FLOAT, sizeof(TextureVertex2D), textureTriangles[0].textureVertex[0].vertex);
glTexCoordPointer(2, GL_FLOAT, sizeof(TextureVertex2D), textureTriangles[0].textureVertex[0].texture);

/*
textureTriangles is filled and the texture image is loaded in
*/

Для сохранения в реальном VBO, я попробовал два метода (оба из которых имели одинаковый результат)

// Option 1
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
memcpy(vbo_buffer, textureTriangles[0].textureVertex[0].vertex, 360 * sizeof(TextureTriangle2D));
glUnmapBufferOES(GL_ARRAY_BUFFER); 

// Option 2
glBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureVertex2D), 360 * sizeof(TextureTriangle2D), textureTriangles[0].textureVertex[0].vertex);

Затем я связываю буфер

glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);

И, наконец, выполнить рисунок

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glDrawArrays(GL_TRIANGLES, 0, 3*360);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

Без VBO рисунок работает нормально. После того, как я добавил код VBO выше, рисунок больше не находится в правильном месте (смещен на несколько пикселей), и он блокирует все мое приложение. Есть идеи?

Ответы [ 2 ]

1 голос
/ 06 января 2012

При использовании VBO последний аргумент gl...Pointer - это не указатель на некоторый массив, содержащий данные вершины, а смещение в байтах на текущую границу GL_ARRAY_BUFFER.Таким образом, вы не указываете адреса данных вершин вашего ЦП, которые вы уже скопировали в буфер, а смещений в этих данных буфера, где хранятся атрибуты:

glVertexPointer(2, GL_FLOAT, sizeof(TextureVertex2D), 
    offsetof(TextureVertex2D,vertex));
glTexCoordPointer(2, GL_FLOAT, sizeof(TextureVertex2D), 
    offsetof(TextureVertex2D,texture));
0 голосов
/ 06 января 2012

В этой строке:

glBufferData(GL_ARRAY_BUFFER, sizeof(TextureTriangle2D)*360, textureTriangles[0].textureVertex[0].vertex, GL_DYNAMIC_DRAW);

Я думаю, что вы должны указать sizeof(TextureTriangle2D)*360*3, поскольку для каждого треугольника (используя GL_TRIANGLES в запросе массива рисования) требуются 3 координаты вершин.

Iне очень много информации о передаче трехмерных координат, используя только 2 координаты (я полагаю, что Z установлен на ноль?), но само объявление должно быть проверено на вашей стороне

Я бы ожидал:

typedef struct {
    GLfloat vertex[3];
    GLfloat texture[2];
    GLfloat padding[3];
} TextureVertex2D;

Но это во многом зависит от вашего двигателя.

...