Comment gérez-vous plusieurs textures dans un tableau de tampon indexé OpenGL pour une utilisation avec un shader données?

StackOverflow https://stackoverflow.com/questions/1678925

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!

Était-ce utile?

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)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top