Чередование VBO, вызывающее ошибку glDrawArrays () - PullRequest
3 голосов
/ 18 апреля 2011

Недавно я изменил свое приложение с использования OpenGL ES 1.1 на 2.0, и в процессе я решил дополнительно оптимизировать свой код с помощью VBO.Я думаю, что я должен разобраться с основными различиями с ES 2.0, и есть результаты, чтобы показать, что я делаю вещи правильно без VBO, однако я был озадачен проблемой, которая возникает, только когда я пытаюсь использовать VBO.

Я использую пользовательскую структуру, содержащую положение, цвет и размер вершины (плюс небольшой отступ для выравнивания данных), а затем чередую эти данные вершины в VBO.Эти данные используются для отображения точечных спрайтов.Проблема в том, что я получаю EXC_BAD_ACCESS при вызове glDrawArrays ().Обратный след при этой ошибке следующий:

#0  0x31fc7358 in gleRunVertexSubmitARM ()
#1  0x31fc87b2 in gleLLVMArrayFunc ()
#2  0x31fc872a in gleSetVertexArrayFunc ()
#3  0x31fbefcc in gleDrawArraysOrElements_ExecCore ()
#4  0x31fc4608 in glDrawArrays_IMM_Exec ()
#5  0x36ddaee2 in glDrawArrays ()
#6  0x0001cab8 in -[Renderer renderDrawingVertexBuffer:withSize:usingTexture:] (self=0x1783b0, _cmd=0x50fec, vboID=0, size=3584, drawTexture=5) at /Users/Stu/Documents/...
#7  0x000202f4 in -[EAGLView drawSmoothCurveFromPoints:endOfLine:] (self=0x195be0, _cmd=0x50d34, points=0x1956f0, endOfLine=1 '\001') at /Users/Stu/Documents/...
#8  0x0001e50c in -[EAGLView drawView:] (self=0x195be0, _cmd=0x50d8a, sender=0x0) at /Users/Stu/Documents/...
#9  0x0001e174 in -[EAGLView layoutSubviews] (self=0x195be0, _cmd=0x3297d4ac) at /Users/Stu/Documents/...
#10 0x326805fa in -[UIView(CALayerDelegate) layoutSublayersOfLayer:] ()
#11 0x35efbf02 in -[NSObject(NSObject) performSelector:withObject:] ()
#12 0x333fbbb4 in -[CALayer layoutSublayers] ()
#13 0x333fb96c in CALayerLayoutIfNeeded ()

Это структура для хранения данных вершин:

typedef struct {
    ISVertex2D vertex;     // Made up of 2 GLfloats.
    ISColor    color;      // Made up of 4 GLfloats.
    GLfloat    size;
    GLfloat    padding;
} ISPointSpriteData;

После того, как набор данных сохранен в массиве этих структур,данные отправляются в VBO и обрабатываются с использованием glDrawArrays ():

[renderer prepareScene];
[renderer renderBackground];

glBindBuffer(GL_ARRAY_BUFFER, penVbo);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(ISPointSpriteData) * penVboSize, sizeof(ISPointSpriteData) * vertexCount, &vertexBuffer[0].vertex);

glBindTexture(GL_TEXTURE_2D, drawTexture);

glEnableVertexAttribArray(ATTRIB_VERTEX);
glEnableVertexAttribArray(ATTRIB_COLOR);
glEnableVertexAttribArray(ATTRIB_SIZE);
glDisableVertexAttribArray(ATTRIB_TEXTURE_COORD);
glUniform1i(uniforms[UNIFORM_IS_SPRITE], GL_TRUE);

glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, vertex));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, color));
glVertexAttribPointer(ATTRIB_SIZE, 1, GL_FLOAT, GL_FALSE, sizeof(ISPointSpriteData), (void*)offsetof(ISPointSpriteData, size));

glDrawArrays(GL_POINTS, 0, vertexCount);     // <--- EXC_BAD_ACCESS

glDisableVertexAttribArray(ATTRIB_VERTEX);
glDisableVertexAttribArray(ATTRIB_COLOR);
glDisableVertexAttribArray(ATTRIB_SIZE);


[renderer presentScene];

Этот код работал до того, как я вставил VBO, единственное изменение состояло в том, что последний параметр вызовов glVertexAttribPointer ()очевидно, указывают на данные, а не на смещение.Что мне не хватает?Я не думаю, что этот код особенно сложен, поэтому я могу только думать, что где-то допустил глупую ошибку.

Спасибо

Ответы [ 2 ]

4 голосов
/ 19 апреля 2011

Проблема решена:

В моем коде было несколько ошибок, не все из которых были бы очевидны из списков в вопросе.Я обрисую основные проблемы:

  • В коде, не указанном в списке, я создавал VBO в служебной функции.В этой функции я неправильно передавал дескриптор GLuint для буфера (я пытался передать его по ссылке в функцию, которая возвращает void).Чтобы сделать его более читабельным, я изменил функцию, чтобы просто инициализировать ее собственный дескриптор и вернуть ее.Это остановило сбой программы в строке glDrawArrays() (предположительно, неинициализированное значение должно быть уже назначено другому буферу где-то).

Появилась новая проблема - экран стал черным ибыли большие задержки между звонками.Это было вызвано ...

  • Не отменять привязку VBO после каждого вызова розыгрыша.Для каждого кадра сначала рисуется фоновая текстура, а затем содержимое VBO.Оставив VBO на следующем фоновом рендере, я, очевидно, заставил OGL немного подойти!Это стало причиной не только черного экрана, но и больших задержек между вызовами на отрисовку.

Надеюсь, это поможет кому-то другому в подобной ситуации!

0 голосов
/ 18 апреля 2011

Возможно, вам придется использовать glDrawElements вместо glDrawArrays. Потому что glDrawArrays не позволяет прыгать или пропускать. Он читает из непрерывного набора вершин.

"glDrawArrays () считывает данные вершин из включенных массивов, проходя прямо через массив без пропуска или скачкообразного изменения. Поскольку glDrawArrays () не позволяет переключаться между массивами вершин, вам все равно придется повторять общие вершины один раз для каждой грани. «

http://www.songho.ca/opengl/gl_vertexarray.html

...