glDrawElements бросает EXC_BAD_ACCESS с использованием VBO в OpenGL ES 3.0

Эта проблема сводит меня с ума, потому что это кажется правильным. Я работаю с iOS 7 и OpenGL ES 3.0.

Типы переменных:

float vertices[24];
unsigned short indices[24];
unsigned char colors[32];
unsigned int vboIds[3];

Это выполняется только один раз:

vertices[0] = -0.5f; vertices[1] = -0.5f; vertices[2] = 0.5f;
vertices[3] = 0.5f; vertices[4] = -0.5f; vertices[5] = 0.5f;
vertices[6] = 0.5f; vertices[7] = 0.5f; vertices[8] = 0.5f;
vertices[9] = -0.5f; vertices[10] = 0.5f; vertices[11] = 0.5f;
vertices[12] = -0.5f; vertices[13] = -0.5f; vertices[14] = -0.5f;
vertices[15] = 0.5f; vertices[16] = -0.5f; vertices[17] = -0.5f;
vertices[18] = 0.5f; vertices[19] = 0.5f; vertices[20] = -0.5f;
vertices[21] = -0.5f; vertices[22] = 0.5f; vertices[23] = -0.5f;

indices[0] = 0; indices[1] = 1; // front
indices[2] = 1; indices[3] = 2;
indices[4] = 2; indices[5] = 3;
indices[6] = 3; indices[7] = 0;

indices[8] = 4; indices[9] = 5; // back
indices[10] = 5; indices[11] = 6;
indices[12] = 6; indices[13] = 7;
indices[14] = 7; indices[15] = 4;

indices[16] = 0; indices[17] = 4; // sides
indices[18] = 1; indices[19] = 5;
indices[20] = 2; indices[21] = 6;
indices[22] = 3; indices[23] = 7;

for (size_t i = 0;i<8;++i) {
    colors[i*4+0] = (unsigned char)((vertices[i*3+0]+0.5)*255);
    colors[i*4+1] = (unsigned char)((vertices[i*3+1]+0.5)*255);
    colors[i*4+2] = (unsigned char)((vertices[i*3+2]+0.5)*255);
    colors[i*4+3] = 255;
}

GL(glGenBuffers(3, vboIds));

GL(glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]));
GL(glBufferData(GL_ARRAY_BUFFER, sizeof(float)*24, vertices, GL_STATIC_DRAW));

GL(glBindBuffer(GL_ARRAY_BUFFER, vboIds[1]));
GL(glBufferData(GL_ARRAY_BUFFER, sizeof(char)*32, colors, GL_STATIC_DRAW));

GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[2]));
GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*24, indices, GL_STATIC_DRAW));

И это всегда выполняется при рендеринге:

GL(glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]));
GL(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float)*3, 0));
GL(glEnableVertexAttribArray(0));

GL(glBindBuffer(GL_ARRAY_BUFFER, vboIds[1]));
GL(glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(char)*4, 0));
GL(glEnableVertexAttribArray(1));

GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[2]));

GL(glDrawElements(GL_LINES, 24, GL_UNSIGNED_SHORT, 0));

GL(glDisableVertexAttribArray(0));
GL(glDisableVertexAttribArray(1));

GL(glBindBuffer(GL_ARRAY_BUFFER, 0));
GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));

glDrawElements(...) выдает EXC_BAD_ACCESS (код=1, адрес=0x0), и я не знаю почему.


person Alex Moreno    schedule 21.04.2014    source источник
comment
Поскольку я не видел ничего плохого, я попробовал код. Мне было лень создавать проект для iOS, но я поместил его в приложение GLUT на своем Mac. Он не падает и отрисовывает квадрат, чего я и ожидал, потому что не применял никаких преобразований. Так что либо в iOS что-то другое, либо в коде что-то происходит, чего мы здесь не видим. Одна рекомендация: я бы использовал определенные в GL типы для вершинных данных, такие как GLushort, GLuchar, GLfloat и т. д. Нет никакой гарантии, что, например, GLushort и unsigned short являются одним и тем же типом на каждой платформе. Я думаю, что они на iOS.   -  person Reto Koradi    schedule 22.04.2014
comment
Я только что попытался изменить тип данных на OpenGL, и он выдает ту же ошибку.   -  person Alex Moreno    schedule 22.04.2014


Ответы (1)


Я решил это, поместив:

GL(glGenBuffers(3, vboIds));

GL(glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]));
GL(glBufferData(GL_ARRAY_BUFFER, sizeof(float)*24, vertices, GL_STATIC_DRAW));

GL(glBindBuffer(GL_ARRAY_BUFFER, vboIds[1]));
GL(glBufferData(GL_ARRAY_BUFFER, sizeof(char)*32, colors, GL_STATIC_DRAW));

GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[2]));
GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*24, indices, GL_STATIC_DRAW));

внутри метода InitGL, а не в конструкторе.

person Alex Moreno    schedule 22.04.2014
comment
Если у вас был код в конструкторе, ваш объект, вероятно, был создан до того, как контекст был создан и стал текущим. Когда я пишу классы C++, которые инкапсулируют объекты GL, я всегда использую метод типа init для создания объектов GL. Если это делается в конструкторе, слишком легко случайно создать объект до того, как контекст будет готов. - person Reto Koradi; 22.04.2014