Un objet tampon de vertex ( VBO ) est une fonctionnalité OpenGL qui fournit des méthodes pour télécharger des données de vertex ( position , vecteur normal , couleur, etc.) sur le périphérique vidéo pour un rendu en mode non immédiat. Les VBO offrent des gains de performances substantiels par rapport au rendu en mode immédiat, principalement parce que les données résident dans la mémoire du périphérique vidéo plutôt que dans la mémoire système et qu'elles peuvent donc être rendues directement par le périphérique vidéo. Ils sont équivalents aux tampons de vertex dans Direct3D .
La spécification de l'objet vertex buffer a été normalisée par l'OpenGL Architecture Review Board Archivé le 24/11/2011 sur la Wayback Machine à partir de la version 1.5 d'OpenGL (en 2003). Des fonctionnalités similaires étaient disponibles avant la normalisation des VBO via l' extension "vertex array range" créée par Nvidia ou l'extension "vertex array object" d' ATI .
Fonctions VBO de base
Les fonctions suivantes constituent le cœur de l’accès et de la manipulation du VBO :
- Dans OpenGL 1.4 :
- glGenBuffersARB (taillei n, uint *buffers)
- Génère un nouveau VBO et renvoie son numéro d'identification sous forme d'entier non signé. L'identifiant 0 est réservé.
- glBindBufferARB (cible d'énumération, tampon uint)
- Utilisez un tampon précédemment créé comme VBO actif.
- glBufferDataARB (cible d'énumération, taille de l'énumération sizeiptrARB, const void *data, utilisation de l'énumération)
- Télécharger les données vers le VBO actif.
- glDeleteBuffersARB (taille, const uint *buffers)
- Supprime le nombre spécifié de VBO du tableau fourni ou de l'ID VBO.
- Dans OpenGL 2.1 , OpenGL 3.x et OpenGL 4.x :
- glGenBuffers (taillei n, uint *buffers)
- Génère un nouveau VBO et renvoie son numéro d'identification sous forme d'entier non signé. L'identifiant 0 est réservé.
- glBindBuffer (cible d'énumération, tampon uint)
- Utilisez un tampon précédemment créé comme VBO actif.
- glBufferData (cible d'énumération, taille de l'énumération sizeiptrARB, const void *data, utilisation de l'énumération)
- Télécharger les données vers le VBO actif.
- glDeleteBuffers (taille, const uint *buffers)
- Supprime le nombre spécifié de VBO du tableau fourni ou de l'ID VBO.
Exemple d'utilisation
En C, en utilisant OpenGL 2.1
//Initialiser VBO - ne faire qu'une seule fois, au démarrage du programme //Créer une variable pour contenir l'identifiant VBO GLuint triangleVBO ; //Sommets d'un triangle (enroulement dans le sens inverse des aiguilles d'une montre) float data [] = { 1.0 , 0.0 , 1.0 , 0.0 , 0.0 , -1.0 , -1.0 , 0.0 , 1.0 }; //essayez float data[] = { 0.0 , 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0}; si ce qui précède ne fonctionne pas. //Créez un nouveau VBO et utilisez la variable id pour stocker l'ID VBO glGenBuffers ( 1 , & triangleVBO ); // Rendre le nouveau VBO actif glBindBuffer ( GL_ARRAY_BUFFER , triangleVBO ); //Télécharger les données de vertex sur le périphérique vidéo glBufferData ( GL_ARRAY_BUFFER , sizeof ( data ), data , GL_STATIC_DRAW ); //Rendre le nouveau VBO actif. Répétez cette opération ici au cas où il aurait changé depuis l'initialisation glBindBuffer ( GL_ARRAY_BUFFER , triangleVBO ); //Dessiner un triangle à partir de VBO - effectuer chaque modification de fenêtre temporelle, de point de vue ou de données //Établir ses 3 coordonnées par sommet avec un pas nul dans ce tableau ; nécessaire ici glVertexPointer ( 3 , GL_FLOAT , 0 , NULL ); // Établir un tableau contenant des sommets (pas des normales, des couleurs, des coordonnées de texture, etc.) glEnableClientState ( GL_VERTEX_ARRAY ); //Dessinez réellement le triangle, en donnant le nombre de sommets fournis glDrawArrays ( GL_TRIANGLES , 0 , sizeof ( data ) / sizeof ( float ) / 3 ); //Forcer l'affichage à être dessiné maintenant glFlush ();
En C, en utilisant OpenGL 3.x et OpenGL 4.x
Shader de sommet :
/*----------------- "exempleVertexShader.vert" -----------------*/ #version 150 // Spécifiez quelle version de GLSL nous utilisons. // in_Position était lié à l'indice d'attribut 0("shaderAttribute") dans vec3 in_Position ; void main ( ) { gl_Position = vec4 ( in_Position.x , in_Position.y , in_Position.z , 1.0 ) ; } / * -------------------------------------------------------------- * /
Shader de fragments :
/*---------------- "exempleFragmentShader.frag" ----------------*/ #version 150 // Spécifiez quelle version de GLSL nous utilisons. précision highp float ; // Les pilotes de la carte vidéo nécessitent cette ligne pour fonctionner correctement sortie vec4 fragColor ; void main () { fragColor = vec4 ( 1.0 , 1.0 , 1.0 , 1.0 ); // Définir la couleur de chaque fragment sur BLANC } /*--------------------------------------------------------------*/
Programme OpenGL principal :
/*--------------------- Programme OpenGL principal ---------------------*/ /* Créer une variable pour contenir l'identifiant VBO */ GLuint triangleVBO ; /* Ceci est un handle vers le programme shader */ GLuint shaderProgram ; /* Ces pointeurs recevront le contenu de nos fichiers de code source de shader */ GLchar * vertexSource , * fragmentSource ; /* Ce sont des handles utilisés pour référencer les shaders */ GLuint vertexShader , fragmentShader ; const unsigned int shaderAttribute = 0 ; /* Sommets d'un triangle (enroulement dans le sens inverse des aiguilles d'une montre) */ float data [ 3 ][ 3 ] = { { 0.0 , 1.0 , 0.0 }, { -1.0 , -1.0 , 0.0 }, { 1.0 , -1.0 , 0.0 } }; /*---------------------- Initialiser le VBO - (Remarque : ne le faire qu'une seule fois, au démarrage du programme) ---------------------*/ /* Créer un nouveau VBO et utiliser la variable "triangleVBO" pour stocker l'ID du VBO */ glGenBuffers ( 1 , & triangleVBO ); /* Rendre le nouveau VBO actif */ glBindBuffer ( GL_ARRAY_BUFFER , triangleVBO ); /* Télécharger les données de vertex sur le périphérique vidéo */ glBufferData ( GL_ARRAY_BUFFER , sizeof ( data ), data , GL_STATIC_DRAW ); /* Spécifiez que nos données de coordonnées vont dans l'index d'attribut 0 (shaderAttribute) et contiennent trois flottants par sommet */ glVertexAttribPointer ( shaderAttribute , 3 , GL_FLOAT , GL_FALSE , 0 , 0 ); /* Activer l'index d'attribut 0 (shaderAttribute) comme étant utilisé */ glEnableVertexAttribArray ( shaderAttribute ); /* Rendre le nouveau VBO actif. */ glBindBuffer ( GL_ARRAY_BUFFER , triangleVBO ); /*-------------------------------------------------------------------------------------------------------*/ /*--------------------- Charger les shaders Vertex et Fragment à partir de fichiers et les compiler --------------------*/ /* Lire nos shaders dans les tampons appropriés */ vertexSource = filetobuf ( "exampleVertexShader.vert" ); fragmentSource = filetobuf ( "exampleFragmentShader.frag" ); /* Attribuer à nos handles un « nom » aux nouveaux objets shader */ vertexShader = glCreateShader ( GL_VERTEX_SHADER ); fragmentShader = glCreateShader ( GL_FRAGMENT_SHADER ); /* Associer les tampons de code source à chaque handle */ glShaderSource ( vertexShader , 1 , ( const GLchar ** ) & vertexSource , 0 ); glShaderSource ( fragmentShader , 1 , ( const GLchar ** ) & fragmentSource , 0 ); /* Libérer la mémoire temporairement allouée */ free ( vertexSource ); free ( fragmentSource ); /* Compilez nos objets shader */ glCompileShader ( vertexShader ); glCompileShader ( fragmentShader ) ; /*-------------------------------------------------------------------------------------------------------*/ /*-------------------- Créez un programme de shader, attachez-lui des shaders puis liez-le ---------------------*/ /* Attribuez à notre handle de programme un "nom" */ shaderProgram = glCreateProgram (); /* Attachons nos shaders à notre programme */ glAttachShader ( shaderProgram , vertexShader ); glAttachShader ( shaderProgram , fragmentShader ); /* Lier l'index d'attribut 0 (shaderAttribute) à in_Position*/ /* "in_Position" représentera le contenu du tableau "data" dans le vertex shader */ glBindAttribLocation ( shaderProgram , shaderAttribute , "in_Position" ); /* Programme de shader de lien */ glLinkProgram ( shaderProgram ); /*-------------------------------------------------------------------------------------------------------*/ /* Définir le programme shader comme étant activement utilisé */ glUseProgram ( shaderProgram ); /* Définir la couleur d'arrière-plan sur NOIR */ glClearColor ( 0.0 , 0.0 , 0.0 , 1.0 ); /* Effacer l'arrière-plan avec la couleur NOIRE */ glClear ( GL_COLOR_BUFFER_BIT ); /* Dessinez réellement le triangle, en donnant le nombre de sommets fourni par l'appel de glDrawArrays tout en indiquant que nos données sont un triangle et que nous voulons dessiner 0 à 3 sommets */ glDrawArrays ( GL_TRIANGLES , 0 , ( sizeof ( data ) / 3 ) / sizeof ( GLfloat )); /*---------------------------------------------------------------*/