Programmation Graphique Haute Performance Premiers

Transcription

Programmation Graphique Haute Performance Premiers
Programmation Graphique Haute Performance
Premiers pas en C++ et OpenGL
January 9, 2012
Ressources
• Qt est un toolkit graphique portable écrit en C++ permetant la création d’applications graphiques
complexes. Dans le cadre de ces TDs, cette bibliothèque sera utilisée uniquement pour la création
du context OpenGL, la gestion des fenêtres, et le chargement d’images. (documentation)
• Eigen est une bibliothèque C++ d’algèbre linéaire. Elle sera utilisée pour la représentation
et manipulation de matrices, vecteurs, transformations géométriques et résolution de sysèmes
d’équations. (documentation)
• Cmake sera utilisé pour gérer la compilation du projet. (tutorial, documentation)
1
Prise en main
1.1
Compilation
1. Télécharger et décompresser l’archive:
$ wget http://www.labri.fr/perso/guenneba/pghp_2012/pghp_td1.tgz
$ tar xzf pghp_td1.tgz
2. Créer un répertoire de build, configurer, et compiler:
$
$
$
$
mkdir build-td1
cd build-td1
cmake ../pghp_td1 -DQT_QMAKE_EXECUTABLE=/usr/bin/qmake-qt4
make
3. Exécuter le programme. Dans l’état actuel, aucune opération de tracé n’est réalisée.
4. Parcourir la classe RenderingWidget et en déduire l’ordre d’exécution des fonctions lors de l’exécution
du programme. A l’aide des fonctions glClearColor() et glClear() faire en sorte d’otenir une fenêtre
correctement initialisée d’une couleur uniforme (par example blanche).
1.2
Visualisation d’un maillage 3D
1. Dans la fonction Mesh::drawGeometry(), compléter les appels à glVertexAttribPointer et glDrawElements de manière en envoyer à OpenGL l’ensemble du maillage triangulaire. Vous devez obtenir
un carré rouge centré.
1
2. Les maillages 3D sont souvent définis avec une échelle arbitraire. Compléter la méthode Mesh::makeUnitary()
de manière à centrer le maillage sur l’origine, et que sa plus grande dimension soit de 1. Attention
à la préservation des proportions du modèle. Modifier la méthode RenderingWidget::createScene()
de manière à charger le modèle data/tw.off.
3. Le modèle tw.off représente un personnage où l’axe z représente la verticale. Modifier le shader
shaders/simple.vert pour visualiser le personnage de face et non de dessus.
4. Modifier le shader afin de visualiser les coordonnées x, y, z du maillage sous forme d’une couleur
RGB.
5. Modifier le shader pour que le modèle soit deux fois plus petit.
6. Modifier le shader pour que l’échelle de l’objet soit controllable à l’exécution. Il faut pour cela
ajouter une variable uniform qui sera controllée par le programme principal via la fonction glUniform1f. Vous pouvez utiliser la fonction Shader::getUniformLocation(const char*) pour obtenir
l’identifiant d’une variable uniform.
7. Via la méthode RenderingWidget::keyPressEvent, faire en sorte que l’échelle de l’objet soit controllée par les touches haut et bas du clavier. Pour forcer le tracer OpenGL il faut appeler la
fonction updateGL(). La fonction paintGL() sera alors appelée ultérieurement. Ne surtout pas
appeler paintGL() directement.
2
Multi-vues
1. En jouant avec la fonction glViewport(), scinder la fenêtre OpenGL en deux horizontalement, et
tracer le modèle 3D dans chacune des zones.
2. Afin de visualiser le modèle 3D sous deux angles de vues (par exemple de face et de coté), généraliser
le shader de manière à appliquer une transformation générique représentée sous la forme d’une
matrice 4 × 4 (type mat4 en GLSL). Indications:
• En GLSL le produit entre une matrice M et un vecteur v est réalisé par l’opérateur *: M * v.
• Pour spécifier les valeurs d’une matrice uniform utiliser la fonction glUniformMatrix4fv.
• Utiliser le type Eigen::Matrix4f pour créer une matrice de 4 × 4 flotants compatible avec
OpenGL. Ex.:
Eigen::Matrix4f M;
M << 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1;
La fonction M.data() retourne un pointeur vers le 1er élément.
3. Scinder la fenêtre en 4 et tracer l’objet 3D avec 4 vues différentes: face, coté, dessus, et une
projection isométrique. Vous pourez former la matrice de projection isométrique en combinant des
rotations élémentaires autour des axes x, y, et/ou z.
Eigen::Matrix4f mat;
Eigen::Matrix3f rotation_matrix = ( Eigen::AngleAxisf(M_PI, Eigen::UnitY())
* Eigen::AngleAxisf(M_PI/2, Eigen::UnitX())
).toRotationMatrix();
mat.block<N,M>(i,j) = ...; // retourne une vue de la sous matrice de
// dimension NxM commençant à la position (i,j)
Voici un exemple de que vous devez obtenir :
2
3