gKit2 light
Loading...
Searching...
No Matches
tuto9_buffers.cpp

cf tuto9_buffers.cpp

le tuto précédent a montré comment manipuler un shader openGL pour dessiner un Mesh, ce tuto explique rapidement comment créer et configurer le vertex buffer et le vertex array qui permettent de dessiner directement un Mesh avec openGL.

que font Mesh et draw(mesh, program) pour afficher un objet ? comme expliqué dans le tuto précédent, les attributs de sommets doivent se trouver dans la mémoire de la carte graphique pour que les vertex shader s'exécutent correctement.

la mémoire de la carte graphique est séparée de la mémoire de l'application : il n'est pas possible de faire un malloc ou un new directement, mais openGL propose des buffers comme mécanisme d'allocation de mémoire.

il faut d'abord créer un identifiant de buffer, cf glGenBuffers(), et le sélectionner pour le manipuler, cf glBindBuffer() :

GLuint buffer;
glGenBuffers(1, &buffer);
// selectionne le buffer
glBindBuffer(GL_ARRAY_BUFFER, buffer);

pour donner la taille du buffer, et son contenu, cf glBufferData() :

// selectionner le buffer, si necessaire :
// glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, /* size */, /* data */, /* usage */ GL_STATIC_DRAW);

le dernier paramètre, GL_STATIC_DRAW, indique que le contenu du buffer ne sera pas modifié plus tard.

dernière étape, décrire le format des sommets du Mesh avec un vertex array object : même démarche, il faut créer un identifiant, cf glGenVertexArrays(), le sélectionner, cf glBindVertexArray(), et le configurer, cf glVertexAttribPointer() :

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// selectionner le buffer contenant les positions, si nécessaire,
// c'est un parametre implicite de glVertexAttribPointer !!
// glBindBuffer(GL_ARRAY_BUFFER, buffer);
// configurer l'attribut 0, position, cf convention de Mesh
glVertexAttribPointer( /* attribute */ 0,
3, GL_FLOAT, // size et type, position est un vec3 dans le vertex shader
GL_FALSE, // pas de normalisation des valeurs
0, // stride 0, les valeurs sont les unes a la suite des autres
0 // offset 0, les valeurs sont au debut du buffer
);
// utiliser l'attribut 0
glEnableVertexAttribArray(0);

voila, les coordonnées des sommets du Mesh sont transférées dans un buffer, l'attribut est configuré dans un vertex array object, il suffira de le sélectionner avant le glDraw() pour dessiner l'objet :

// configuration minimale du pipeline openGL
glUseProgram( ... );
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, n);

dernier détail, il ne faut pas oublier de conserver le nombre de sommets, et il n'est plus nécessaire de conserver l'objet Mesh !

cf configurer un format de sommet, vertex array object pour les détails supplémentaires, utiliser plusieurs buffers, plusieurs attributs, etc.

tuto9_buffers.cpp donne un exemple complet et stocke toutes les informations dans une structure Buffers :

struct Buffers
{
GLuint vao;
GLuint vertex_buffer;
int vertex_count;
Buffers( ) : vao(0), vertex_buffer(0), vertex_count(0) {}
void create( const Mesh& mesh )
{
if(!mesh.vertex_buffer_size()) return;
// cree et configure un vertex array object: conserve la description des attributs de sommets
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// cree et initialise le buffer stockant les positions des sommets
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, mesh.vertex_buffer_size(), mesh.vertex_buffer(), GL_STATIC_DRAW);
// attention : le buffer est implicite, c'est celui qui est selectionne sur GL_ARRAY_BUFFER
// attribut 0, position des sommets, declare dans le vertex shader : layout(location= 0) in vec3 position;
glVertexAttribPointer(0, // numero de l'attribut, cf declaration dans le shader
3, GL_FLOAT, // size et type, position est un vec3 dans le vertex shader
GL_FALSE, // pas de normalisation des valeurs
0, // stride 0, les valeurs sont les unes a la suite des autres
0 // offset 0, les valeurs sont au debut du buffer
);
glEnableVertexAttribArray(0); // numero de l'attribut, cf declaration dans le shader
// attention : le vertex array selectionne est un parametre implicite
// attention : le buffer selectionne sur GL_ARRAY_BUFFER est un parametre implicite
// conserve le nombre de sommets
vertex_count= mesh.vertex_count();
}
void release( )
{
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vertex_buffer);
}
};
// init de l'application :
Mesh mesh= read_mesh("data/cube.obj");
if(!mesh.vertex_count()) return -1;
// creer le vertex buffer et le vao
m_objet.create(mesh);
// mesh n'est plus necessaire
mesh.release();
// draw de l'application :
// selectionner le program
glUseProgram( );
// parametrer le program, cf tuto9
{ ... }
// selectionner les buffers et les attributs de l'objet
glBindVertexArray(m_objet.vao);
// dessiner les triangles de l'objet
glDrawArrays(GL_TRIANGLES, 0, m_objet.vertex_count);
representation d'un objet / maillage.
Definition mesh.h:121
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
Definition wavefront.cpp:14

les différentes variantes de glDraw() sont expliquées dans glDraw( ) et la famille.

euh ? plus simple ?

on peut aussi demander à Mesh de créer et d'initialiser les buffers, avec Mesh::create_buffers( ) :

// init de l'application :
Mesh mesh= read_mesh( ... );
count= mesh.vertex_count();
vao= mesh.create_buffers( ); // initialise tous les attibuts du mesh
program= read_program( ... );
// draw de l'application :
glBindVertexArray(vao);
glUseProgram(program);
{ ... } // initialiser les paramètres uniforms des shaders.
glDrawArrays(GL_TRIANGLES, 0, count);
GLuint read_program(const char *filename, const char *definitions)
Definition program.cpp:218

on peut aussi préciser quels attributs doivent être initialisés en plus de position. par exemple pour créer un vertex buffer ne contenant que les positions et les normales des sommets :

vao= mesh.create_buffers( USE_POSITION | USE_NORMAL );
@ USE_POSITION
inclut l'attribut position dans les buffers.
Definition mesh.h:112
@ USE_NORMAL
inclut l'attribut normale dans les buffers.
Definition mesh.h:114

les attributs standards sont USE_POSITION, USE_NORMAL, USE_TEXCOORD, USE_COLOR, et USE_MATERIAL_INDEX. cf première application avec des shaders pour les détails et comment les utiliser dans un shader.