M2 - Images
TP 1 - Transformations
et visibilité
documents à
remettre le 15/11/2010
Envoyez en utilisant
le mail de l'université une archive des sources de votre
tp ainsi qu'un rapport de quelques pages précisant les
tansformations et algorithmes utilisés pour chaque exercice.
Vous préciserez vos noms, prénoms et numéros
d'étudiants dans le corps du mail.
L'objectif de cette partie du tp est de mettre en place les
transformations nécessaires pour dessiner plusieurs objets
décrits par des
primitives non planes, des triangles de Bézier (description de
la
construction dans "Curved
PN
Triangles").
Chaque primitive est décrite par un ensemble de sommets. Chaque
sommet "subit" l'ensemble standard de
transformations : modèle, vue, projection et fenêtre.
Pour vous faire gagner du temps, installez gKit.
Partie 1 : transformations d'un sommet.
exercice 1 : mise en jambe.
Appliquez l'enchainement de transformations à un sommet p et
vérifiez sa visibilité.
Si le sommet est visible, dessinez un pixel dans l'image
résultat.
Utilisez des transformations "identité" dans un premier temps,
mais définissez toutes les étapes de la chaîne de
transformation.
Quel est l'espace visible définit par des transformations
identité ?
exercice 2 : transformations.
Modifiez les transformations "identité" et vérifiez que
les résultats sont toujours corrects. Par exemple :
- utilisez une matrice de projection perspective :
gk::Perspective(50.f, 1.f, 1.f, 1000.f);
- déplacez la caméra : gk::Translate( gk::Vector(0.0,
0.0, 50.0) );
Partie 2 : transformations d'une primitive.
exercice 1 : primitive plane.
Transformez chaque sommet d'un triangle abc.
Affichez le triangle si, au moins un, de ses sommets est visible.
La solution la plus simple pour dessiner un triangle est de
générer un "grand" ensemble de points appartenant au
triangle. Puis, pour chaque point de vérifier s'il est visible
et de déterminer sur quel pixel il se projette.
rappel :
utilisez l'interpolation barycentrique sur les positions des sommets
abc pour générer des points appartenant au triangle.
p(u, v, w)= w*a + u*b + v*c
avec u, v, w compris entre 0 et 1, ainsi que u+v+w=
1 (ou w= 1 - u - v).
remarque : il existe plusieurs conventions, vérifiez
avant de faire une supposition en lisant un article, par exemple.
p(u, v)= (1-u-v)*a + u*b + v*c, ou p(u, v)= u*a +
v*b + (1-u-v)*c ... ou p(u, v)= a + u*(b-a) + v*(c-a)
question bonus : comment "contrôler" la quantité de points
générée pour dessiner le triangle ? il faudrait,
idéalement, générer un point par pixel ...
Un résumé compact du problème et une solution
possible : "Perspective-Correct
Interpolation".
remarque : une autre idée pour dessiner un triangle consiste
à le découper
jusqu'à ce que ses 3 sommets se projettent sur le même
pixel.
exercice 2 : ne dessiner que ce qui visible.
Mêmes questions que l'exercice 1, mais en subdivisant les parties
non entièrement visibles du triangle.
L'objectif est de ne dessiner que des "morceaux" du triangle totalement
visibles.
Est-ce que dessiner des "morceaux" entièrement visibles change
quelque chose à l'algorithme d'affichage ?
question bonus : élimination des parties cachées.
Comment déterminer qu'un triangle n'est pas
visible ? sans tester la visibilité de chaque sommet.
Ce simple test permet d'éliminer jusqu'à 50% des
triangles d'un objet.
exercice 3 : plusieurs objets décrits par des primitives
planes.
On souhaite maintenant afficher plusieurs objets décrits par des
primitives planes.
Que faut-il faire pour dessiner l'ensemble d'objets en tenant compte de
leur visibilité ?
exercice 4 : primitive non plane.
Mêmes questions que l'exercice 2, mais avec un triangle non plan,
un triangle de Bézier. cf "Curved
PN
Triangles" pour la construction des points de controles et la
description de la méthode de remaillage.
question bonus : et avec une construction différente, par
exemple "Phong
Tessellation" ? certaines opérations sont plus simples,
lesquelles ?
exercice 5 : plusieurs objets décrits par des primitives non
planes.
Mêmes quesions que l'exercice 3 mais avec des primitives non
planes.
question bonus : élimination des parties cachées.
L'élimination des triangles non orientés vers la
caméra permet d'éliminer de l'ordre de 50% des triangles
et donc de dessiner l'objet plus rapidement. Mais il reste encore des
triangles non visibles qui seront dessinés puis rejetés,
pixel par pixel, par le z-buffer puisqu'ils sont "cachés"
derrière un autre triangle déja dessiné. Il est
possible de construire un autre "z-buffer" capable de rejetter un
triangle avant de le dessiner lorsqu'il
est derrière une partie déja dessinée,
et donc d'améliorer les performances. Comment ?
Partie 3 : Ombres et lumières
exercice 1 :
Représentez une source de lumière ponctuelle et une
matière simple (diffuse pour commencer).
Calculer la couleur de chaque point affiché en fonction de sa
normale, de la position de la source de lumière et de sa
matière.
exercice 2 :
Même question avec une matière
réfléchissante.
exercice 3 :
Mêmes questions avec plusieurs sources de lumières.
question bonus : et les ombres ?
Annexes : outils
gKit est une petite librairie proposant plusieurs outils, comme des
classes : gk::Point, gk::HPoint, gk::Vector, gk::Normal, gk::Matrix4x4,
gk::Transform, des fonctions de calcul gk::Translate, gk::RotateXYZ,
etc. gKit permet aussi de
charger des objets, de lire et d'enregistrer des images, etc.
télécharger gKit (release
221)
lisez la doc !
voici quelques exemples d'utilisation :
gk::Image *image= new
gk::Image(1024, 768); // cree une image de dimensions
1024x768 pixels.
gk::Transform model; // transformation
identité
gk::Transform projection= gk::Perspective(50.f, 1.f, 1.f,
1000.f); // projection perspective
gk::Transform viewport= gk::Viewport(image->width(),
image->height()); // transformation
adaptee a la resolution de l'image resultat
// compose les transformations, sauf viewport : produit dans le
sens inverse des changements de reperes representes ...
gk::Transform mvp= projection * view * model;
gk::Point p; // un point x, y, z "réel".
gk::HPoint ph; // point x, y, z, w "homogene",
resultat de la projection.
mvp(p, ph); //
transforme le point p pour obtenir ph.
gk::Point q= ph.project() // retrouve le point
réel correspondant au point homogène.
gk::Point q= viewport(ph.project()); //
determine sur quel pixel se projette un point visible.
image->setPixel( q.x, q.y, gk::Pixel(255, 255, 255)
); // dessine un pixel blanc sur la projection du
point p (visible).
gk::ImageIO::write(image, "output.bmp"); //
écrit l'image dans un fichier .bmp.