M2 Image

TP1 - prise en main



Partie 1 :  installez gKit

cf la rubrique installation de la doc.

modifiez un des tutos, par exemple le tuto6 (version plutot "c") ou le tuto7 (version plutot "c++") pour afficher une grille de cubes :



affichez le temps cpu et gpu (cf classe AppTime).

quelles remarques peut on faire sur le temps cpu et le temps gpu en fonction de la taille de la grille / du nombre de cubes affiches ?
est ce que le temps d'affichage varie selon la position de la camera ?

peut-on esperer afficher un monde type minecraft avec ce type de solution ?


Partie 2 : shaders

compilez shader_kit, fournit avec gKit

utilisez shader_kit pour construire un shader qui affecte un type de terrain et une couleur à chaque triangle du terrain :

que doivent faire, au minimum, le vertex shader et le fragment shader ?
consultez la doc de shader_kit
relisez dans le résumé de GLSL, le langage des shaders openGL

charger le terrain Clipboard02.obj

la carte d'altitude utilisée pour générer le terrain : Clipboard02.png
cf en annexe, le code de génération.

bin/shader_kit shader.txt clipboard02.obj




Partie 3 : et avec openGL ?


modifiez le programme de la partie 1 pour dessiner directement avec openGL. Le mieux est de faire les modifications progressivement, en suivant les tuto9_shader et tuto9_buffer :
    1. utilisez le shader minimaliste du tuto9 pour dessiner les cubes, au lieu de laisser draw() le faire à votre place,
    2. changez la couleur des cubes...
    3. créez les buffers et configurez le vertex array object et dessiner directement

quelle variante de glDraw() parait la plus adaptée pour dessiner plusieurs fois le meme objet ? modifiez votre programme en conséquence.
dans un premier temps, concentrez vous sur la position des cubes.

comment dessiner des cubes de couleurs différentes et continuer à utiliser la variante efficace de glDraw() ?





enrichissez votre fonction de generation de type de terrain. comment obtenir les informations sur l'altitude des voisins, les pentes, etc ?

obervez comment minecraft représente chaque matiere : par exemple chez dokucraft

un seul type de shader peut il afficher tous les types de briques / cubes ? l'eau ? l'herbe ? les arbres etc ? comment structurer le code d'affichage ?




annexe : génération du terrain à partir d'une carte d'altitude :


Mesh make_terrain( const char *filename )
{
    Mesh mesh(GL_TRIANGLES);
   
    Image data= read_image(filename);
   
    float scale= 20;
   
#if 0
    // solution 1 : genere un maillage directement, duplique les sommets des triangles.
    for(int y= 0; y +1 < data.height(); y++)
    for(int x= 0; x +1 < data.width(); x++)
    {
        // recupere l'altitude de 4 points voisins, dans le sens trigo
        float a= data(x, y).r * scale;
        float b= data(x +1, y).r * scale;
        float c= data(x +1, y +1).r * scale;
        float d= data(x, y +1).r * scale;
       
        // construit 2 triangles avec les 4 points
        // le terrain est constuit dans le plan xz, et y est l'altitude
       
        // rappel : la camera regarde -Z, pas +Z, il faut construire le terrain sur +x -z (et pas +x +z)
        // en gros utiliser -y au lieu de y comme coordonnee z, sinon les triangles sont "retournes"...
        mesh.texcoord(x, y).vertex(Point(x, a, -y));
        mesh.texcoord(x+1, y).vertex(Point(x +1, b, -y));
        mesh.texcoord(x+1, y+1).vertex(Point(x +1, c, -y -1));
       
        mesh.texcoord(x, y).vertex(Point(x, a, -y));
        mesh.texcoord(x+1, y+1).vertex(Point(x +1, c, -y -1));
        mesh.texcoord(x, y+1).vertex(Point(x, d, -y -1));
    }

#else
    // solution 2 : genere un maillage indexe.
   
    // genere les positions des sommets sur la grille
    for(int y= 0; y < data.height(); y++)
    for(int x= 0; x < data.width(); x++)
    {
        // recupere l'altitude du sommet
        float a= data(x, y).r * scale;
       
        // genere la coordonnee de texture
        mesh.texcoord(float(x) / data.width(), float(y) / data.height());
        // genere la position
        mesh.vertex(x, a, -y);
    }
   
    // genere les triangles indexes
    for(int y= 0; y +1 < data.height(); y++)
    for(int x= 0; x +1 < data.width(); x++)
    {
        // recupere les 4 voisins et genere 2 triangles
       
        // recalcule l'indice des sommets generes par la premiere etape
        int a= y * data.width() + x;
        int b= y * data.width() + (x+1);
        int c= (y+1) * data.width() + (x+1);
        int d= (y+1) * data.width() + x;
       
        mesh.triangle(a, b, c);
        mesh.triangle(a, c, d);
    }
#endif

    return mesh;
}