Буферный объект OpenGL Vertex, могу ли я получить доступ к данным вершины для других целей, таких как обнаружение столкновений? - PullRequest
5 голосов
/ 21 июня 2011

В настоящее время я использую классы GLTools, которые идут вместе с Superbible 5th edition. Я смотрю в классе GLTriangleBatch, и он имеет следующий код:

// Create the master vertex array object
glGenVertexArrays(1, &vertexArrayBufferObject);
glBindVertexArray(vertexArrayBufferObject);


// Create the buffer objects
glGenBuffers(4, bufferObjects);

#define VERTEX_DATA     0
#define NORMAL_DATA     1
#define TEXTURE_DATA    2
#define INDEX_DATA      3

// Copy data to video memory
// Vertex data
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA]);
glEnableVertexAttribArray(GLT_ATTRIBUTE_VERTEX);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pVerts, GL_STATIC_DRAW);
glVertexAttribPointer(GLT_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);

// Normal data
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[NORMAL_DATA]);
glEnableVertexAttribArray(GLT_ATTRIBUTE_NORMAL);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pNorms, GL_STATIC_DRAW);
glVertexAttribPointer(GLT_ATTRIBUTE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0);

// Texture coordinates
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[TEXTURE_DATA]);
glEnableVertexAttribArray(GLT_ATTRIBUTE_TEXTURE0);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*2, pTexCoords, GL_STATIC_DRAW);
glVertexAttribPointer(GLT_ATTRIBUTE_TEXTURE0, 2, GL_FLOAT, GL_FALSE, 0, 0);

// Indexes
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*nNumIndexes, pIndexes, GL_STATIC_DRAW);

// Done
glBindVertexArray(0);

// Free older, larger arrays
delete [] pIndexes;
delete [] pVerts;
delete [] pNorms;
delete [] pTexCoords;

// Reasign pointers so they are marked as unused
pIndexes = NULL;
pVerts = NULL;
pNorms = NULL;
pTexCoords = NULL;

Из того, что я понимаю, код переходит к массивам, которые указатели pVerts, pNorms, pTexCoords, pIndexes, и сохраняет их в объекте массива Vertex, который по сути является массивом объектов буфера вершин. Они хранятся в памяти на GPU. Исходные указатели затем удаляются.

Мне интересно получить доступ к позициям вершин, которые содержались в массиве, на который указывал pVert.

Теперь мой вопрос вращается вокруг обнаружения столкновений. Я хочу иметь доступ к массиву всех вершин моего GLTriangleBatch. Могу ли я получить их через vertexBufferObject позже, используя какой-нибудь метод получения? Было бы лучше просто держать указатель pVerts и использовать вместо этого метод getter? Я думаю о производительности, так как надеюсь реализовать алгоритм обнаружения столкновений GJK в будущем ...

1 Ответ

7 голосов
/ 21 июня 2011

Буферные объекты, используемые в качестве источников данных вершин, существуют для рендеринга .Переход назад (чтение данных назад), как правило, не рекомендуется с точки зрения производительности.

Подсказка, которую вы даете glBufferData, имеет три шаблона доступа: DRAW, READ и COPY;они сообщают OpenGL, как вы собираетесь получать / извлекать данные из объекта буфера напрямую.Подсказки не управляют тем, как OpenGL должен читать / записывать с него / на него.Это всего лишь подсказки;API не обеспечивает какого-либо конкретного поведения, но его нарушение может привести к снижению производительности.

DRAW означает, что вы будете помещать данные в буфер, но не будете читать из него.READ означает, что вы будете читать данные из буфера, но не будете писать в него (обычно для обратной связи преобразования или пиксельных буферов).И COPY означает, что вы не будете ни читать, ни записывать в буфер напрямую.

Обратите внимание, что нет подсказки для «чтения и записи».Есть только «написать», «прочитать» и «ни то, ни другое».Учтите, что намек на то, насколько хорошей является идея записать данные в буфер напрямую, а затем начать чтение из этого буфера.

Опять же, подсказки предназначены для пользователя, непосредственно получающего или получающего данные.glBufferData, glBufferSubData, и все различные функции отображения делают запись, в то время как glGetBufferSubData и все функции отображения делают чтение.

В любом случае нет, вы не должны этого делать.Храните копию данных о местоположении в памяти клиента, если вам нужно использовать ее на клиенте.

Кроме того, некоторые драйверы полностью игнорируют советы по использованию.Вместо этого они решают, где разместить буферный объект, основываясь на том, как вы на самом деле его используете, а не на том, как вы собираетесь его использовать.Это будет хуже для вас, потому что если вы начнете читать из этого буфера, драйвер может переместить данные буфера в память, которая не так быстро.Он может быть перемещен из графического процессора и даже в пространство памяти клиента.

Однако, если вы настаиваете на этом, есть два способа чтения данных из объекта буфера.glGetBufferSubData является обратным glBufferSubData.И вы всегда можете сопоставить буфер для чтения вместо записи.

...