lorsqu'une application doit dessiner beaucoup d'objets, l'organisation des donnes  un impact sur les performances. par exemple, dans un code simple, 
les donnes de chaque objet sont stockes dans un ou plusieurs buffers et la configuration des attributs est stocke dans un vertex array object. pour afficher 
plusieurs objets, on aura donc une boucle qui slectionne le vao de l'objet avant de le dessiner :
\code
    struct Object
    {
        GLuint vao;
        GLuint program;
        GLuint texture;
        int vertex_count;
        Transform model;
    };
    
    std::vector<Object> scene;
    
    // remplir la description de la scene
    { ... }
    
    // afficher la scene
    Transform vp= { ... };      // composition de view et projection
    for(int i= 0; i < scene.size(); i++)
    {
        glBindVertexArray(scene[i].vao);
        glUseProgram(scene[i].program);
        program_uniform(scene[i].program, "mvpMatrix", vp * scene[i].model);
        program_use_texture(scene[i].program, "diffuseTexture", scene[i].texture);
        
        glDrawArrays(GL_TRIANGLES, 0, scene[i].vertex_count);
    }
\endcode

malheureusement, changer de vao et de shader demande pas mal de travail au driver, et cette solution est trs lente.

il est possible de gagner pas mal de temps en stockant toutes les donnes des objets dans le mme buffer et en utilisant un seul vao, ce qui permet
d'crire la boucle d'affichage de manire plus efficace.
le buffer stocke les sommets des objets, les uns aprs les autres, il faut donc se rappeller ou commence la description de chaque objet et utiliser le 
paramtre first de glDrawArrays() :
\code
    struct Object
    {
        GLuint program;
        GLuint texture;
        int begin;
        int vertex_count;
        Transform model;
    };
    
    std::vector<Object> scene;
    
    // remplir la description de la scene
    { ... }
    
    // afficher la scene
    glBindVertexArray(vao);
    for(int i= 0; i < scene.size(); i++)
    {
        glUseProgram(program);
        program_uniform(scene[i].program, "mvpMatrix", vp * scene[i].model);
        
        glDrawArrays(GL_TRIANGLES, scenes[i].begin, scene[i].vertex_count);
    }
\endcode

__remarque :__ grosso modo, les changements les plus couteux sont, en ordre dcroissant, changer de shader, changer de texture, changer de vao, 
changer de  buffer. changer la valeur d'un uniform est bien plus rapide.

__remarque :__ oui, il est quasi ncessaire de limiter le nombre de shaders utiliss au total dans la scne. une solution courante consiste  trier les objets 
par shader et  les dessiner avec le nombre minimal de glUseProgram()...

__remarque :__ et re-oui, il faut aussi faire la mme chose avec les textures, soit trier les objets par paire de (shader, texture), soit packer les textures 
dans une seule grande texture (un atlas de texture), soit utiliser un tableau de textures, cf GL_TEXTURE_2D_ARRAY. tout ca pour limiter le nombre de fois ou 
il faut changer de shader avec glUseProgram() et de texture avec glBindTexture().
