5

J'utilise actuellement les classes GLTools qui accompagnent la 5ème édition de Superbible. Je suis à la recherche dans la classe GLTriangleBatch et il a le code suivant:Objet tampon OpenGL Vertex, puis-je accéder aux données de vertex pour d'autres utilisations telles que la détection de collision?

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

D'après ce que je comprends le code passe les tableaux que les pointeurs pVerts, pNorms, pTexCoords, pIndexes et les stocke dans un objet tableau Vertex, qui est essentiellement un tableau d'objets de tampon vertex. Ceux-ci sont stockés en mémoire sur le GPU. Les pointeurs d'origine sont ensuite supprimés.

Je suis intéressé par l'accès aux positions de vertex, qui ont été maintenues dans le tableau pVert pointé vers. Maintenant, ma question tourne autour de la détection de collision. Je veux être en mesure d'accéder à un tableau de tous les sommets de mon GLTriangleBatch. Puis-je les obtenir via le vertexBufferObject à un moment ultérieur en utilisant une sorte de méthode getter? Serait-il préférable de garder le pointeur pVerts et d'utiliser une méthode getter à la place? Je pense en termes de performance, car j'espère implémenter un algorithme de détection de collision GJK à l'avenir ...

Répondre

7

Les objets tampons, utilisés comme sources pour les données de vertex, existent au profit de rendant. Revenir en arrière (lire les données en arrière) n'est généralement pas conseillé du point de vue de la performance.

L'indication que vous donnez à glBufferData a trois modèles d'accès: DRAW, READ et COPY; ceux-ci disent à OpenGL comment vous avez l'intention d'obtenir/récupérer des données de l'objet tampon directement. Les indices ne gouvernent pas la façon dont OpenGL devrait lire/écrire depuis/vers. Ce ne sont que des indices; l'API n'applique aucun comportement particulier, mais les enfreindre peut entraîner de mauvaises performances. DRAW signifie que vous allez mettre des données dans le tampon, mais vous ne pourrez pas en lire. READ signifie que vous allez lire les données du tampon, mais vous n'écrirez pas dessus (généralement pour les commentaires de transformation ou les tampons de pixels). Et COPY signifie que vous ne pourrez ni lire ni écrire directement dans le tampon.

Notez qu'il n'y a pas d'indice pour "lire et écrire". Il n'y a que "écrire", "lire" et "ni". Considérez qu'un indice quant à la qualité d'une idée consiste à écrire des données directement dans un tampon, puis à commencer à lire à partir de ce tampon.

Encore une fois, les indications sont pour l'utilisateur directement obtenir ou récupérer des données. , glBufferSubData, et les diverses fonctions de mappage font toutes des écritures, alors que glGetBufferSubData et les fonctions de mappage font toutes des lectures.

Dans tous les cas non, vous ne devriez pas faire cela. Conservez une copie des données de position dans la mémoire du client si vous avez besoin de l'utiliser sur le client.

En outre, certains pilotes ignorent complètement les conseils d'utilisation. Ils décident plutôt de placer l'objet tampon en fonction de la façon dont vous l'utilisez réellement, plutôt que de la manière dont vous dites que vous avez l'intention de l'utiliser. Ce sera pire pour vous, car si vous commencez à lire à partir de ce tampon, le pilote peut déplacer les données du tampon vers la mémoire qui n'est pas aussi rapide. Il peut être déplacé hors du GPU et même dans l'espace mémoire du client. Toutefois, si vous insistez pour le faire, il existe deux façons de lire les données d'un objet tampon. glGetBufferSubData est l'inverse de glBufferSubData. Et vous pouvez toujours mapper le tampon pour lire au lieu d'écrire.

+1

Merci beaucoup! Cette réponse a été très utile! Je vais garder le pointeur pVert pour accéder aux données de vertex plus tard. – kbirk

+0

@ user785259: Garder juste le pointeur n'est pas suffisant. Vous devez en fait conserver la mémoire allouée, c'est-à-dire ne pas supprimer delete() ou free (...). Même après avoir libéré de la mémoire, vous pouvez toujours avoir le pointeur sur C, qui n'est alors pas valide. Peut-être que vous venez d'un langage collecté par les ordures, alors rejeter un pointeur implique en fait de libérer de la mémoire, et oui, c'est la sémantique saine. Mais c'est le C++ auquel vous avez affaire et tout ce tapage est une nécessité incontournable là-bas. – datenwolf

Questions connexes