Comment gérez-vous plusieurs textures dans un tableau de tampon indexé OpenGL pour une utilisation avec un shader données?
-
16-09-2019 - |
Question
Je tente de mettre en œuvre cet article . J'ai avoir la plus grande partie vers le bas, mais la partie sur l'envoi arbitraires, des données non géométriques au shader pour une utilisation dans la détermination et l'affichage des bords géométriques me causer des problèmes. J'ai réussi à envoyer avec succès la plupart de mes données tout en utilisant bien ce que je sais VBOs. Cependant, je dois envoyer une grande quantité de données, ce qui nécessite l'utilisation de plusieurs coordonnées de texture.
Je l'ai déjà mis en œuvre plusieurs variations de ce que je crois être la bonne façon de mettre en place plusieurs jeux de coordonnées de texture, et suivi les instructions de nombreuses affiches du forum. Aucune solution de travail à ce jour.
Pour le contexte, le programme est d'envoyer 4 copies presque identiques d'un ensemble de 4 sommets, 2 vecteurs normaux, un flotteur, et un entier (stocké en tant que flotteur) pour chaque arête unique dans le modèle. J'ai exposé les données comme ceci:
v0 is stored in gl_Vertex (vec3)
v1 is stored in gl_Color (vec3)
v2 is stored in gl_MultiTexCoord0 (vec3)
v3 is stored in gl_MultiTexCoord1 (vec3)
n0 is stored in gl_Normal (vec3)
n1 is stored in gl_SecondaryColor (vec3)
r and i are stored in gl_MultiTexCoord2 (vec2)
La seule différence entre les 4 copies est la valeur i, ce qui aide à déterminer comment organiser les sommets si et quand un bord drawable se trouve.
Comme vous pouvez le voir, je dois au moins 3 coordonnées de texture. Je suis en mesure d'obtenir le premier travail (gl_MultiTexCoord0) très bien, mais les coordonnées de texture suivantes, bien que sur la carte graphique, semblent avoir un comportement incontrôlable, travaillant parfois, mais généralement pas.
Ma fonction de rendu utilisé pour ressembler à ceci:
void Mesh::RenderLineEdgesGPU()
{
// Enable client state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Turn on edge shader
edgeProgram.Activate();
// Link buffers
// v0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// v1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
glColorPointer(3, GL_FLOAT, 0, 0);
// v2
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// v3
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// n0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
glNormalPointer(GL_FLOAT, 0, 0);
// n1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
// r and i
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
// Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
// Draw
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// Turn off edge shader
edgeProgram.Deactivate();
// Disable client state
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Ce fut mon original. Il fonctionne vraiment pour v0, v1, et v2. Il semble fonctionner pour « r et i », mais cela pourrait être une illusion. Je n'ai pas la possibilité de tester encore ou n1 n0. v3 certainement ne fonctionne pas. Comme vous pouvez le voir, je les dessin comme points, ce qui me dit s'ils sont là ou non (via le shader). v0, v1, v2 et sont tous là. Toute tentative de faire la même chose pour les rendements v3 soit un seul point à l'origine ou rien du tout.
Après avoir examiné les suggestions en ligne, voici ma nouvelle configuration:
void Mesh::RenderLineEdgesGPU()
{
// Enable client state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
// Turn on edge shader
edgeProgram.Activate();
// Link buffers
// v0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// v1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
glColorPointer(3, GL_FLOAT, 0, 0);
// v2
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// v3
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// n0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
glNormalPointer(GL_FLOAT, 0, 0);
// n1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
// r and i
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
// Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
// Draw
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// Turn off edge shader
edgeProgram.Deactivate();
// Disable client state
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
}
Remarquez comment je l'ai fait les glEnableClientState
/ appels glDisableClientState
autour du « chargement » réel de chaque coordonnée de texture liste. Je l'utilise aussi glActiveTextureARB
et glEnable(GL_TEXTURE_2D)
. Même si je pense que je pourrais comprendre pourquoi glActiveTextureARB
est nécessaire ici, l'autre me déconcerte. Selon le GLSL erreurs communes Page de de href="http://www.opengl.org/wiki/GLSL_:_common_mistakes#Enable_Or_Not_To_Enable", vous n'êtes pas censé utiliser glEnable(GL_TEXTURE_2D)
quand vous faites vos propres shaders, car l'utilisation de shaders ne tient pas compte de cet appel de toute façon.
Alors c'est tout. Je suis arrivé jusqu'ici sans être en mesure de trouver des tutoriels portant spécifiquement sur la façon d'envoyer des données de coordonnées non texture en coordonnées de texture. Peut-être que si quelqu'un connaît un tutoriel sur ce point, mon problème serait atténué. Merci pour votre temps!
La solution
change glClientActiveTextureARB
quelle unité spécifique texture coordinate à la suite d'appels glEnableClientState(GL_TEX_COORD_ARRAY)
et glTexCoordPointer
changera.
glActiveTextureARB
affecte glEnable(GL_TEXTURE_2D)
, qui, comme vous l'avez mentionné, vous n'avez pas besoin pour les shaders.
Si vous regardez votre code près, choisir uniquement les 5 appels (et leur équivalent Désactiver), voici ce que vous avez:
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
Ok, nous avons déjà dit que glActiveTextureARB et glEnable ne sont pas utiles (par la manière, vous activer / désactiver GL_TEXTURE_2D
sans nul entre les deux, ce n'est pas utile), donc les supprimer:
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
Qu'est-ce que signifie maintenant? 2 questions:
- Vous désactivez votre état client avant même d'exécuter tirage
- Vous ne définissez pas le bit d'activation pour texture2
Que devriez-vous écrire? Quelque chose le long de ces lignes: (Attention, vous devrez ajouter le BindBuffer rappelle à chaque appel pointeur):
// texture coord 0
glClientActiveTextureARB(GL_TEXTURE0_ARB); // program texcoord unit 0
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // enable array data to shader
glTexCoordPointer(3, GL_FLOAT, 0, 0); // say what data
// texture coord 1
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// texture coord 2
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// done with those texcoord units, turn them off
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Quelques autres commentaires sur BindBuffer: glBindBufferARB(GL_ARRAY_BUFFER_ARB,...)
ne pas se touchés par le glClientActiveTextureARB
, mais ne affectent le prochain appel de glTexCoordPointer
. En substance, penser à glClientActiveTextureARB
et glBindBufferARB
comme fournissant des arguments supplémentaires pour glTexCoordPointer
.
La dernière chose, vous voulez probablement regrouper certains de ces VBOs en moins des tampons. Quelque chose pour une autre question peut-être? (Conseil, les 2 arguments à glTexCoordPointer
ne doit pas être 0)