OpenGL, glDrawArrays и IOS, плохой доступ? - PullRequest
4 голосов
/ 12 февраля 2012

Я начинаю работать с OpenGL в iOS.Я всегда учился рисовать вещи в OpenGL, используя glBegin() и glEnd(), так что это немного ново для меня.

Я пытаюсь нарисовать простой треугольник.Я могу красиво нарисовать белый треугольник, я даже могу нарисовать целый цветной треугольник, используя glColor.Но всякий раз, когда я пытаюсь назначить цвет каждой вершине, используя этот код ниже, я получаю EXC_BAD_ACCESS при рисовании массива.Я использую симулятор iOS 4.3 для этого.Что я делаю не так?

- (void) render:(CADisplayLink*)displayLink {
    glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    GLfloat vertices [] = {0,0,0, 0,100,0, 100,0,0};
    GLfloat colours [] = {1.0,1.0,1.0, 1.0,1.0,1.0, 1.0,1.0,1.0};
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glColorPointer(3, GL_FLOAT, 0, colours);
    glDrawArrays(GL_TRIANGLES, 0, 3);   <-- CRASHES HERE
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    [self.context presentRenderbuffer:GL_RENDERBUFFER];
}    

Ответы [ 2 ]

5 голосов
/ 12 февраля 2012

Строка glColorPointer(3, GL_FLOAT, 0, colours) генерирует ошибку GL_INVALID_VALUE (вы можете видеть, что выполнение po glGetError сразу после выполнения этой строки выдает 1281).

Причина в том, что OpenGL ES не поддерживает 3 цветовых компонента, документация гласит:

GL_INVALID_VALUE генерируется, если размер не равен 4.

С вашим кодом все будет в порядке, если вы измените количество цветовых компонентов на 4, добавив альфа.

1 голос
/ 12 февраля 2012

Ваш код OpenGL пока выглядит правильным. Вызывает ли glDrawArrays плохой доступ или плохой доступ в нем? Я просто могу представить, что указатель glDrawArrays func не инициализирован, однако, массивы вершин должны быть доступны.

Вы можете вызвать эту функцию после glEnableClientState(GL_COLOR_ARRAY); в качестве теста для сброса любых других устаревших указателей массива, которые могут вызвать плохой доступ:

///@brief Emulation of call glClientAttribDefaultEXT(GL_CLIENT_VERTEX_ARRAY_BIT) according to GL_EXT_direct_state_access.

static void ClientAttribDefaultVertexArray(void) {
    int i;
    GLint max;

    glBindBufferARB(GL_ARRAY_BUFFER, 0);
    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);

    glDisableClientState(GL_EDGE_FLAG_ARRAY);
    glEdgeFlagPointer(0, 0);

    glDisableClientState(GL_INDEX_ARRAY);
    glIndexPointer(GL_FLOAT, 0, 0);

    glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
    glSecondaryColorPointer(4, GL_FLOAT, 0, 0);

    glDisableClientState(GL_FOG_COORD_ARRAY);
    glFogCoordPointer(GL_FLOAT, 0, 0);

    glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max);
    for (i = 0; i < max; ++i) {
        glClientActiveTextureARB(GL_TEXTURE0 + i);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(4, GL_FLOAT, 0, 0);
    }

    glDisableClientState(GL_COLOR_ARRAY);
    glColorPointer(4, GL_FLOAT, 0, 0);

    glDisableClientState(GL_NORMAL_ARRAY);
    glNormalPointer(GL_FLOAT, 0, 0);

    glDisableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(4, GL_FLOAT, 0, 0);

    glDisableClientState(GL_WEIGHT_ARRAY_ARB);
    glWeightPointerARB(0, GL_FLOAT, 0, 0);

    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max);
    for (i = 0; i < max; ++i) {
        glDisableVertexAttribArrayARB(i);
        glVertexAttribPointerARB(i, 4, GL_FLOAT, GL_FALSE, 0, 0);
    }

    glClientActiveTextureARB(GL_TEXTURE0);
}

Кроме того, вы можете нажать и вытолкнуть состояние массива вершин в стеке attrib клиента:

glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);

///vertex array init and usage

glPopClientAttrib();
...