M2 - Images
TP 1 - Transformations
et visibilité
documents à
rendre pour le 28/10/2011:
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
(notamment la méthode de "remplissage" de triangles).
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 (la définition
paramétrique d'un triangle) 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).
cf. gk::Triangle::getUVPoint()
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 : "DirectX
11
Reyes
Rendering"
remarques :
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 ?
question bonus : intersection rayon / pn triangle ?
Comment utiliser des pn triangles dans un lancer de rayons ?
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
455)
lisez la doc !
remarque: la plupart des fonctions de
calcul sont documentees dans le namespace gk
a faire: grouper la documentation par
"theme"
voici quelques exemples d'utilisation :
gk::Image *image= new
gk::Image(1024, 768); // cree une image de dimensions
1024x768 pixels.
gk::Transform model; // transformation
par défaut, 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.
Annexes : utiliser la librairie gKit et premake4
remarques pour l'installation :
pensez à compiler la version de glew fournie avant d'essayer de
compiler la librairie:
cd glew-1.7.0
make
les makefiles sont générés automatiquement par premake4.
Comment créer un programme
utilisant gKit ?
le plus simple est d'ajouter une ligne dans le fichier de description
de projet : premake4.lua, éditez le et trouvez la section :
--~ liste des projets / programmes a construire, en utilisant la
librairie gKit
local projets = {
"image_viewer",
"tuto1",
"tuto2"
}
il suffit d'ajouter le nom de votre fichier sans l'extension cpp
et de re-générer le makefile :
--~ liste des projets / programmes a construire, en utilisant la
librairie gKit
local projets = {
"image_viewer",
"tuto1",
"tuto2",
"tp1"
}
premake4 --os=linux gmake
make tp1
exemple complet : tp1_tutos.tar.gz