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