Programmation Graphique Haute Performance Normal

Transcription

Programmation Graphique Haute Performance Normal
Programmation Graphique Haute Performance
Normal mapping
13 février 2012
1
Normal mapping sur un plan
1. Récupérez l’archive du TP 5 sur le site du cours et décompressez la dans votre répertoir pghp
(là où se trouve le repertoire src). Elle contient 3 fichiers : un modèle de quad avec coordonnées
de textures (quad.obj), une diffuse map représentant un sol (diffuse.ppm), et la normal map
associée (normal.ppm).
Chargez le modèle et les 2 textures dans la carte graphique. Vous aurez besoin de deux identifiants
de textures - donnez leurs des noms explicites ! Appliquez ces textures sur le quad pour vérifier
que tout fonctionne.
2. Comme son nom l’indique, la normal map contient les normales que nous allons utiliser, encodées
sous forme de couleurs. Utilisez ces normales à la place de celles passées par le vertex shader et
testez.
Attention ! Les textures sont faites pour contenir des couleurs, soit 4 nombres compris dans [0 : 1],
alors que les valeurs de nos normales sont comprises dans [-1:1]. Pensez à faire la transformation
appropriée !
3. Appliquez une rotation à l’objet, que constatez-vous ? Que se passe-t-il si vous testez sur autre
chose qu’un plan ?
2
Normal mapping sur un objet quelconque
Dans l’exercice précédent, les normales définies dans la texture étaient exprimées dans le même repère
que les normales du plan : un triplet [rgb] = [001] induisait une normale orthogonale au plan, celui-ci
étant exprimé dans le repère xy. Il s’agit donc d’un cas particulier où vecteurs utilisés pour les calculs
d’éclairement étant exprimés dans le même repère. Cette relation n’est plus valide dans le cas d’un objet
plus complexe : il devient nécessaire de calculer l’éclairement dans le repère local de chaque point. Ce
repère local (l’espace tangent) est défini par trois vecteurs :
• La normale n,
• La tangente t,
• La binormale (ou bitangente) b.
Ces vecteurs aux sommets peuvent être calculés de façon similaire aux normales : pour chaque sommet,
nous prendrons la moyenne des tangentes et bitangentes de faces adjacentes. Pour plus de détails sur
la façon de faire ces calculs, vous pouvez chercher sur le net (essayez tangent space calculation) ou
regarder vos notes de cours. Vous aurez besoin de résoudre un petit système linéaire : Vous pouvez le
faire à la main, ou chercher dans la documentation d’Eigen pour une méthode plus simple...
La matrice :


T = t
b
1
n
Permet donc de transformer un point de l’espace tangent à l’espace objet.
Nous pourrions passer cette matrice au fragment shader afin de transformer la normale contenue dans
la texture (en espace tangent) dans l’espace objet, puis ensuite calculer l’éclairage comme précédemment.
Cependant, cette méthode n’est pas très efficace : il faut passer 3 vecteurs du vertex shader au
fragement shader, et faire une multiplication matrice-vecteur par fragment !
Une solution plus élégante est de transformer, dans le vertex shader, les vecteurs vue v et lumière l
dans l’espace tangent.
Avec cette méthode, il n’y a plus qu’à transférer 2 vecteurs au fragment shader, et les multiplications
de matrices se font par vertex et non par fragment.
Il nous faut donc la matrice qui permet de passer de l’espace objet à l’espace tangent.
Celle-ci est T −1 et peut se calculer directement avec Eigen en faisant :
M.inverse();
1. Ajoutez une méthode computeTangentSpace() à la classe Mesh qui calcule les vecteurs t et b.
Vous aurez besoin de rajouter un/des attribut(s) à la structure Vertex.
Essayez d’éviter de stocker deux fois les normales et pensez à modifier la méthode drawGeometry
pour refléter vos changements.
Si tout va bien, en testant votre programme à ce point, vous devriez avoir la même chose qu’avant.
Visualisez t et b sous forme de couleur pour voir si vous avez un résultat cohérent.
Astuce GLSL : vous pouvez récupérer la ieme colonne d’une matrice M en faisant M[i].
2. Exprimez les vecteurs v et l dans l’espace tangent dans le vertex shader, puis transmettez-les au
fragment shader.
Utilisez-les pour calculer l’éclairage !
2