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.

modèle triangulé    modèle subdivisé avec des pn triangles



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 :

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