5

В настоящее время я использую классы GLTools, которые поставляются вместе с Superbible 5th edition. Я ищу в классе GLTriangleBatch и имеет следующий код:OpenGL Vertex buffer object, могу ли я получить доступ к данным вершин для других целей, таких как обнаружение конфликтов?

// 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, который по существу представляет собой массив вершинных буферных объектов. Они хранятся в памяти на графическом процессоре. Исходные указатели затем удаляются.

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

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

ответ

7

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

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

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

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

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

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

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

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

+1

Спасибо! Этот ответ был очень полезен! Я буду держать указатель pVert для доступа к данным вершин позже. – kbirk

+0

@ user785259: Сохранение указателя не является достаточным. Фактически вы должны сохранить выделенную память, то есть не 'delete []' или 'free (...)' it. Даже после освобождения памяти у вас может быть указатель на C, который тогда недействителен. Возможно, вы исходите из собранного мусора языка, а отбрасывание указателя на самом деле означает освобождение памяти, и да, это разумная семантика. Но это C++, с которым вы имеете дело, и все это nitpicking является неизбежной необходимостью там. – datenwolf