5

Obecnie korzystam z klas GLTools, które towarzyszą edycji Superbible 5th. Szukam w klasie GLTriangleBatch i ma następujący kod:Obiekt bufora OpenGL Vertex, czy mogę uzyskać dostęp do danych wierzchołków dla innych zastosowań, takich jak wykrywanie kolizji?

// 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; 

Z tego co rozumiem kod przechodzi tablice że Wskaźniki pVerts, pNorms, pTexCoords, pIndexes i przechowuje je w tablicy obiektu Vertex, która zasadniczo jest tablicą obiektów bufora wierzchołków. Są one przechowywane w pamięci na GPU. Oryginalne wskaźniki są następnie usuwane.

Jestem zainteresowany dostępem do pozycji wierzchołków, które były utrzymywane w tablicy wskazywanej przez pVert.

Teraz moje pytanie dotyczy wykrywania kolizji. Chcę mieć dostęp do tablicy wszystkich wierzchołków mojego GLTriangleBatch. Czy mogę je uzyskać za pomocą vertexBufferObject w późniejszym czasie, używając jakiejś metody gettera? Czy najlepiej byłoby po prostu zatrzymać wskaźnik pVerts i zamiast tego użyć metody getter? Zastanawiam się pod względem wydajności, ponieważ mam nadzieję na wdrożenie algorytmu wykrywania kolizji GJK w przyszłości ...

Odpowiedz

7

Obiekty bufora, gdy są używane jako źródła danych wierzchołków, istnieją dla korzyści renderowania. Przechodzenie do tyłu (odczytywanie danych z powrotem) jest generalnie niewskazane z punktu widzenia wydajności.

Wskazówka, którą podajesz glBufferData, ma trzy wzorce dostępu: DRAW, READ i COPY; te mówią OpenGL, w jaki sposób zamierzasz pobierać/pobierać dane bezpośrednio z obiektu bufora. Wskazówki nie regulują sposobu, w jaki OpenGL powinien odczytać/zapisać z/do niego. To tylko wskazówki; interfejs API nie wymusza określonego zachowania, ale ich naruszenie może prowadzić do niskiej wydajności.

DRAW oznacza, że ​​wprowadzisz dane do bufora, ale nie będziesz z niego czytał. READ oznacza, że ​​będziesz czytał dane z bufora, ale nie będziesz na nie zapisywać (zwykle w celu przetworzenia informacji zwrotnej lub buforów pikseli). A KOPIUJ oznacza, że ​​nie będziesz czytał bezpośrednio z bufora ani go nie zapisał.

Należy zauważyć, że nie ma podpowiedzi dla "odczytu i zapisu". Po prostu "pisz", "czytaj" i "nie". Weźmy pod uwagę, że dobrym pomysłem jest zapisanie danych bezpośrednio do bufora, a następnie rozpoczęcie czytania z tego bufora.

Te wskazówki dotyczą użytkownika, który bezpośrednio pobiera lub odczytuje dane. glBufferData, glBufferSubData, a różne funkcje mapowania są zapisywane, a wszystkie funkcje odczytywane są przez glGetBufferSubData.

W żadnym wypadku nie powinieneś tego robić. Zachowaj kopię danych pozycji w pamięci klienta, jeśli chcesz go użyć na kliencie.

Ponadto niektóre sterowniki całkowicie ignorują wskazówki dotyczące użytkowania. Zamiast tego decydują, gdzie umieścić obiekt buforowy na podstawie tego, jak go faktycznie używasz, a nie w jaki sposób mówisz, że zamierzasz go użyć. To będzie dla Ciebie gorsze, ponieważ jeśli zaczniesz czytać z tego bufora, sterownik może przenieść dane bufora do pamięci, która nie jest tak szybka. Może zostać przeniesiony poza GPU, a nawet do przestrzeni pamięci klienta.

Jednakże, jeśli nalegasz na zrobienie tego, istnieją dwa sposoby odczytywania danych z obiektu bufora. glGetBufferSubData jest odwrotnością glBufferSubData. I zawsze możesz mapować bufor do czytania zamiast pisać.

+1

Dziękujemy! Ta odpowiedź była bardzo pomocna! Będę trzymał wskaźnik pVert wokół, aby uzyskać dostęp do danych wierzchołków później. – kbirk

+0

@ user785259: Przechowywanie wskaźnika nie jest wystarczające. Właściwie musisz zachować przydzieloną pamięć, tzn. Nie "usuń []" lub "uwolnij (...)". Nawet po zwolnieniu pamięci nadal możesz mieć wskaźnik w C, który wtedy jest nieważny. Być może pochodzisz z języka zebranego na śmieci, a odrzucenie wskaźnika faktycznie oznacza uwolnienie pamięci i tak, to jest rozsądna semantyczna. Ale to jest C++, z którym masz do czynienia, a to wszystko jest nieuchronną koniecznością. – datenwolf

Powiązane problemy