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 ^^).
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.
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 :
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
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; } }
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
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; }
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 ?
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); }
Merci d'avance
Partager