glDrawElements EXC_BAD_ACCESS с использованием VBO

У меня проблема с VBO, которую я действительно не понимаю. Моя проблема решается случайным изменением последнего параметра в вызове метода glVertexAttribPointer. Итак, я ищу ответ на вопрос ПОЧЕМУ это вдруг работает или почему мой предыдущий код больше не работает. (просто чтобы лучше понять opengl)

Структура:

typedef struct 
{
    float position[3];
    float color[4];
} Vertex;

Без VBO:

// Get pointers to the data
GLsizei stride = sizeof(Vertex);
const GLvoid *pCoords = &squareVertices[0].position[0];
const GLvoid *pColors = &squareVertices[0].color[0];

// Setup pointers to positions and colors
glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, stride, pCoords);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, stride, pColors);

// Draw
glDrawArrays(GL_TRIANGLES, 0, sizeof(squareVertices) / sizeof(Vertex));

С VBO (это дает мне EXC_BAD_ACCESS)

// Stide
GLsizei stride = sizeof(Vertex);

// Setup pointers to positions and colors
glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, stride, (GLvoid*) (sizeof(float) * 3));

// Draw
glDrawElements(GL_TRIANGLES, sizeof(squareIndices) / sizeof(squareIndices[0]), GL_UNSIGNED_BYTE, 0);

Итак, единственное, что на самом деле отличается, — это вызов glVertexAttribPointer, который имел указатель на данные и теперь имеет фиксированные числа. Кто-нибудь может уточнить это? Заранее спасибо.


person polyclick    schedule 27.12.2011    source источник


Ответы (1)


Когда VBO активен, последний параметр glVertexAttribPointer на самом деле является не указателем, а смещением внутри объекта буфера вершин, приведенным к указателю. Вот как работают VBO: данные были скопированы в какую-то память, управляемую графическим драйвером, адрес которой вам неизвестен. На самом деле, у него может даже не быть обычного адреса, если он хранится где-то на вашей видеокарте.

Остальное — обман системы типов C/C++. Система типов далеко не настолько умна, чтобы понять, что последний аргумент glVertexAttribPointer должен быть целочисленным смещением размером с указатель, когда VBO активен, и указателем в противном случае. Таким образом, для компилятора C++ это должно все время выглядеть как указатель, потому что именно так glVertexAttribPointer (или, скорее, его предшественники glVertexPointer и друзья) были определены изначально. Когда это действительно просто число, мы просто используем приведение типа, чтобы обмануть компилятор.

person wolfgang    schedule 27.12.2011
comment
Вау! Это был быстрый ответ. Действительно ценится. Кристально чистый ;) - person polyclick; 27.12.2011