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 :
- en fonction de son altitude (bleu pour la mer, vert pour les
prairies, les forets, gris pour la roche, blanc pour la neige,
etc),
- et/ou de la pente des triangles pour modifier le type de
terrain (un ebouli en montagne si la pente est tres forte, une
falaise au bord de la mer, des rochers au milieu d'une prairie,
etc...),
- et/ou l'orientation des triangles peut aussi etre utilisee :
un versant de montagne plus vert que le versant oppose, etc...
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;
}