IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

Indices d'un Index Buffer Object non pris en compte [OpenGL 4.x]


Sujet :

OpenGL

  1. #1
    Invité
    Invité(e)
    Par défaut Indices d'un Index Buffer Object non pris en compte
    Bonjour à tous !

    Je cherche à transformer un VBO en une combinaison IBO+VBO. En pratique j'aimerai afficher des objets qui possèdent quelques couleurs unies qui changeront au clic. Jusqu'à présent je me suis surtout appliquée a avoir des vertex et normales valides, je n'ai donc pas de couleur autre que celle donnée par les shaders.

    J'ai commencé par créer un IBO et pointer sur mon ensemble (vertices, normales, id de picking) de manière très linéaire (rassurez-vous, un jour je fusionnerai les vertex et normales identiques ^^).

    Nom : what_i_have.png
Affichages : 255
Taille : 15,5 Ko

    Je me suis dit que l'idéal serait d'avoir mes deux ou trois couleurs au début de mon VBO, et à l'aide de l'IBO pointer vers elles pour les obtenir dans les shaders. Un seul float a changer par clic, c'est super ! J'ai fais un test en ajoutant une valeur au début de mon VBO, et en décalant les indices contenus dans l'IBO.

    Nom : what_i_want.png
Affichages : 240
Taille : 17,0 Ko

    Et là, c'est le drame
    J'ai beau binder l'IBO sur la cible GL_ELEMENT_ARRAY_BUFFER lors du draw, on dirait que la pipeline continue de lire le VBO en commençant par la case 0, alors que cet indice n'est plus présent dans l'IBO.
    Par exemple : si jamais je commence par push_back trois valeurs random dans le VBO suivies du reste de mes valeurs, et que je met le premier indice de l'IBO à trois, je m'attends à avoir le même affichage correct. Les trois premières valeurs du VBO devant être ignorées, vu que leur indice ne sera jamais dans l'IBO. Et pourtant je me retrouve à afficher des triangles [normal.y, normal.z, id] qui ont pour normales le trio [vertex.x, vertex.y, vertex.z] appartenant au point suivant. il y a un décalage, ce qui n'est pas du tout le comportement que j'attends.
    Je me suis demandée si l'IBO est bien pris en compte par la pipeline. Et visiblement oui car, lors du draw, si je remplace mon IBO par un autre vide, alors plus rien ne s'affiche.

    Voici l'initialisation du contenu de mes buffers :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    // _vbo est un vecteur de GLfloat vide.
    // _ibo est un vecteur de GLuint vide.
    GLuint vbo_id = 0;
     
    /*
    _vbo.push_back(42);
    ++vbo_id;
    */
    for (auto mesh = meshs.begin(); mesh != meshs.end(); ++mesh)
    {
        GLfloat id = mesh->getID().toFloat();
        unsigned int size = mesh->getNumberOfTriangles();
     
        for (unsigned int i = 0; i < size; ++i)
        {
            auto triangle = mesh->getTriangle(i);
     
            _vbo.push_back(triangle.vert1.x);
            _vbo.push_back(triangle.vert1.y);
            _vbo.push_back(triangle.vert1.z);
            _vbo.push_back(triangle.vert1.nx);
            _vbo.push_back(triangle.vert1.ny);
            _vbo.push_back(triangle.vert1.nz);
            _vbo.push_back(id);
     
            _vbo.push_back(triangle.vert2.x);
            _vbo.push_back(triangle.vert2.y);
            _vbo.push_back(triangle.vert2.z);
            _vbo.push_back(triangle.vert2.nx);
            _vbo.push_back(triangle.vert2.ny);
            _vbo.push_back(triangle.vert2.nz);
            _vbo.push_back(id);
     
            _vbo.push_back(triangle.vert3.x);
            _vbo.push_back(triangle.vert3.y);
            _vbo.push_back(triangle.vert3.z);
            _vbo.push_back(triangle.vert3.nx);
            _vbo.push_back(triangle.vert3.ny);
            _vbo.push_back(triangle.vert3.nz);
            _vbo.push_back(id);
     
            for (int k = 0; k < 21; ++k)
                _ibo.push_back(vbo_id + k);
            vbo_id += 21;
        }
    }
    Voici de création des buffers avec OpenGL (dans la fonction initializeGL() d'un objet héritant de QOpenGLWidget de Qt)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
        void Display::initializeGL(void)
        {
            initializeOpenGLFunctions();
            checkVersion();
            glEnable(GL_DEPTH_TEST);
            _camera.init();
            _pickingShader = new Shader("Shaders/picking.vertex.shd", "Shaders/picking.fragment.shd");
            _displayShader = new Shader("Shaders/display.vertex.shd", "Shaders/display.fragment.shd");
     
            GLuint VBO;
            glGenBuffers(1, &VBO);
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            unsigned int vbo_size = _peptide->getVerticesArraySize() * sizeof(GLfloat);
            glBufferData(GL_ARRAY_BUFFER, vbo_size, _peptide->getVerticesArray(), GL_STATIC_DRAW);
     
            glGenBuffers(1, &_IBO);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _IBO);
            unsigned int ibo_size = _peptide->getIndicesArraySize() * sizeof(GLuint);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, ibo_size, _peptide->getIndicesArray(), GL_STATIC_DRAW);
     
            glGenVertexArrays(1, &_VAO);
            glBindVertexArray(_VAO);
            /* Vertex attribute */
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (GLvoid*)0);
            glEnableVertexAttribArray(0);
            /* Normal attribute */
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
            glEnableVertexAttribArray(1);
            /* ID attribute */
            glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
            glEnableVertexAttribArray(2);
            ////* color attribute */
            //glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(7 * sizeof(GLfloat)));
            //glEnableVertexAttribArray(3);
            /* Unbind the VAO */
            glBindVertexArray(0);
     
            _isInitialized = true;
        }
    Et ma fonction paintGL() du même objet.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        void Display::paintGL(void)
        {
            glBindVertexArray(this->_VAO);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->_IBO);
     
            /* Display phase */
            glClearColor(0.06f, 0.07f, 0.09f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            _displayShader->use();
            _camera.attach(*_displayShader, _screenWidth, _screenHeight);
            glDrawElements(GL_TRIANGLES, (_peptide->getIndicesArraySize()) / 7, GL_UNSIGNED_INT, (GLvoid*)0);
     
            glBindVertexArray(0);
        }
    Qu'en pensez-vous ? Pourquoi les index dans mon IBO semblent ne pas être pris en compte ? Ai-je oublié de binder quelque chose d'essentiel, ou faut-il utiliser une fonctionnalité spéciale au niveau de l'attribution de pointeurs pour le parcours de l'IBO ?

    Merci d'avance
    Dernière modification par Invité ; 02/10/2015 à 14h26.

  2. #2
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 379
    Points
    11 379
    Billets dans le blog
    10
    Par défaut
    Salut!

    Je pense que tu n'as pas bien compris comment fonctionnent les IBO.

    Un index de ton IBO correspond à un vertex dans ton(tes) VBO(s).
    Donc ton index ne correspond pas à une composante (vx, vy, vz, nx, ny, nz, tx, ty, ...) mais au groupe complet (v+n+t).
    Ce qui fait que pour ton indexation linéaire, ça donne:
    I0 => v0, n0, t0
    I1 => v1, n1, t1
    ...
    Ix => vX, nX, tX.

    Tu peux envisager de découpler v, t, et n en les plaçant dans des VBO différents, mais le résultat sera le même.

    Ensuite, si tu ajoutes un vertex au début de ton VBO, il faut que tu changes les indices dans ton IBO (ben oui, l'indice 0 de ton IBO pointant sur l'ancien vertex 0, qui est maintenant le vertex 1).
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  3. #3
    Invité
    Invité(e)
    Par défaut
    Salut dragonjoker59 !
    Merci pour ta réponse.

    Je n'avais pas du tout compris, ni même envisagé les IBO sous ce sens.
    Grâce à toi je me rends compte que j'ai mal conçu ma structure VBO. Et que les IBO ne sont pas forcément la réponse à mon problème initial. Voici ce qu'il en est :

    Je voulais que le vertex shader reçoive des ensembles (vx, vy, vz, nx, ny, nz, id, cr, cg, cb) pour représenter des macromolécules. Les molécules ont plusieurs atomes, je dois pouvoir sélectionner un atome au clic, pour changer la couleur de cet atome spécifiquement. De ce fait j'ai besoin de beaucoup beaucoup moins de couleurs et id de picking (autant que j'ai d'atomes), que de vertex et normales (nb d'atomes * nb de triangles * 3). Je pensais donc avoir un VBO structuré à peu près ainsi, par exemple pour une molécule de deux atomes :

    cr1, cg1, cb1, id1 // couleur RGB et id de l'atome 1
    cr2, cg2, cb2, id2 // couleur RGB et id de l'atome 2
    vx1, vy1, vz1, nx1, ny1, nz1
    vx2, vy2, vz2, nx2, ny2, nz2
    vx3, vy3, vz3, nx3, ny3, nz3
    vx4, vy4, vz4, nx4, ny4, nz4
    vx5, vy5, vz5, nx5, ny5, nz5
    vx6, vy6, vz6, nx6, ny6, nz6
    etc.

    avec un IBO qui pointe sur le début de mon VBO pour chaque couleur, et pour chaque ID (enfin, avec la vision déformée que j'avais des IBO à l'époque)

    J'ai simplifié mon besoin en parlant d'atomes, mais cela exprime parfaitement le problème auquel je me heurte. Mes structures 3D seront composées de plusieurs sous-parties (minimum 900 triangles la sous-partie, c'est variable) qui n'auront qu'une seule couleur. Ça m'embête un petit peu de devoir stocker 900 fois la même couleur dans le VBO alors que je pensais pouvoir la stocker qu'une fois. Pire, je pensais qu'au clic je n'aurai que trois floats r g et b de mon VBO à changer à l'aide de glBufferSubData(), très facile à trouver car l'id récupéré au clic multiplié par 4 me donnerait le bon indice du VBO.
    Avec ce que je comprends, je ne peux pas faire pointer une partie de l'IBO sur ces couleurs isolées. Je me retrouve donc contrainte a avoir un VBO de ce genre :

    vx1, vy1, vz1, nx1, ny1, nz1, id1, cr1, cg1, cb1
    vx2, vy2, vz2, nx2, ny2, nz2, id1, cr1, cg1, cb1
    vx3, vy3, vz3, nx3, ny3, nz3, id1, cr1, cg1, cb1
    vx4, vy4, vz4, nx4, ny4, nz4, id1, cr1, cg1, cb1
    vx5, vy5, vz5, nx5, ny5, nz5, id2, cr2, cg2, cb2
    vx6, vy6, vz6, nx6, ny6, nz6, id2, cr2, cg2, cb2
    etc.

    Je multiplie presque la taille du VBO par 2, et en plus je dois conserver en ram l'indice de l'emplacement de la couleur de chaque vertex si je veux pouvoir les changer au clic.

    Une molécule peut avoir vraiment beaucoup beaucoup d'atomes, et mon travail doit pouvoir tourner sur des machines relativement peu puissantes, c'est pourquoi j'ai un réel besoin de performances. Ma (mauvaise) compréhension initiale des IBO me semblait une solution : rien a conserver en RAM, trois floats a éditer par clic, un VBO beaucoup plus petit (et je n'avais pas encore mergé les vertex et normales en double), etc.

    Existe-t-il une fonctionnalité en OpenGL qui me permettrait soit de m'approcher de ce que je voulais faire avec les IBO, soit de répondre a mon besoin autrement ?
    Merci d'avance pour votre réponse
    Dernière modification par Invité ; 05/10/2015 à 11h30.

  4. #4
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 379
    Points
    11 379
    Billets dans le blog
    10
    Par défaut
    Tu peux stocker tes différentes couleurs dans une texture, affecter des coordonnées de texture à tes sommets (2 float au lieu de 3, un petit gain quand même). mais tu auras de toute façon des données dupliquées, je ne sais pas s'il est possible de faire autrement.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  5. #5
    Invité
    Invité(e)
    Par défaut
    Hop !

    Je remonte ce sujet pour le passer en résolu. À la toute origine je n'avais pas bien compris en quoi une texture pouvait résoudre mon problème, je ne comprenais simplement pas que c'etait un simple buffer qui peut contenir une information sous n'importe quel format.
    Merci dragonjoker59 pour cette idée qui m'a mis sur la bonne piste

    Je me suis intéressée à des types de buffers ou les éléments sont accessibles à l'aide d'indices depuis mes shaders.
    Comme je faisait également un picking par couleur, je disposais d'un indice pour chaque vertex. Il m'a donc à la fois servi pour les picking par couleurs, mais aussi pour trouver dans un autre buffer sur la CG la couleur d'affichage souhaitée.

    Pour les buffers, je me suis d'abord penchée du côté des Uniform Buffer Object (qui avaient un nom que je trouvais plus proche de ce que je souhaitais faire à l'époque) avent de me rendre compte que ce buffer risquait d'être trop petit dans mon cas, et qu'un Texture Buffer Object était une super alternative : la même chose en plus gros. C'était donc exactement ce qu'il me fallait depuis le début, et je pense que cela pourra aider des personnes dans le même cas que moi à l'avenir.

    Encore merci !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Z-index non pris en compte
    Par laurentSc dans le forum Mise en page CSS
    Réponses: 10
    Dernier message: 28/04/2014, 23h48
  2. [MySQL-5.0] Index non pris en compte
    Par toufika13 dans le forum Requêtes
    Réponses: 5
    Dernier message: 30/04/2013, 17h56
  3. Index non pris en compte
    Par Greyhunter dans le forum Administration
    Réponses: 4
    Dernier message: 11/10/2012, 18h30
  4. index.php non pris en compte
    Par Natsirt dans le forum Apache
    Réponses: 1
    Dernier message: 04/04/2011, 14h13
  5. index non pris en compte dans inner select
    Par eponette dans le forum SQL
    Réponses: 2
    Dernier message: 12/11/2007, 12h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo