I. L'article original▲
Cet article est une adaptation en langue française de 3. OpenGL 4 Matrices, de Donald Urquhart.
II. Introduction▲
OpenGL 3 et 4 ont déprécié et enlevé toutes les opérations matricielles de la bibliothèque OpenGL, ce que certains prennent comme une très bonne chose pour la communauté, bien que cela en rend la prise en main plus difficile pour les débutants. Pour les utilisateurs des versions précédentes, cela signifie qu'on ne pourra plus utiliser des fonctions comme glTranslate ou glRotate.
En ce qui concerne l'affichage en 3D, on utilise généralement un certain nombre de matrices pour créer la scène finale. Il s'agit des matrices de projection, de modèle et de vue. On peut également considérer les matrices de texture ou normales, par exemple, mais, pour simplement positionner des formes dans le monde affiché, on se limitera aux matrices les plus simples. OpenGL 2 et précédents combinaient les matrices de modèle et de vue dans une seule et utilisaient une pile pour y ajouter des matrices de transformation. On pouvait alors retirer la tête de la pile au besoin.
Certains préfèrent utiliser des matrices séparées, pour éviter de contrôler constamment une seule matrice, tout en facilitant l'utilisation des graphes de scène et d'autres techniques de gestion. La manière de gérer cela est totalement libre ; cependant, dans la suite, on utilisera plusieurs matrices.
II-A. Matrice de projection▲
La matrice de projection est une matrice kitxmlcodeinlinelatexdvp4 \times 4finkitxmlcodeinlinelatexdvp qui définit la projection en deux dimensions de la scène 3D. Elle est généralement calculée par une fonction prédéfinie, comme gluPerspective dans les versions précédentes d'OpenGL. La bibliothèque que l'on utilisera fournit une méthode similaire.
II-B. Matrice de vue▲
La matrice de vue, aussi connue sous le nom de matrice de monde, détermine la position de la caméra dans l'espace. On peut l'imaginer comme une matrice globale qui affecte et place tout par rapport à la caméra.
II-C. Matrice de modèle▲
La matrice de modèle est une matrice locale qui affecte les modèles d'une manière plus discrète. Par exemple, pour déplacer, faire tourner ou mettre à l'échelle un objet spécifique, on utilise la matrice locale de cet objet, la matrice de modèle.
II-D. GLM▲
Heureusement, dans le sillage de l'abandon des méthodes de support des matrices d'OpenGL, une bibliothèque de mathématiques a été développée, GLM, l'acronyme de OpenGL Mathematics. Elle a été prévue comme un duplicata des fonctions matricielles de GLSL avec les méthodes de changement d'échelle, de translation et de rotation d'OpenGL 2 et précédents. On peut la trouver sur son site officiel.
L'installation est simple : une fois le fichier téléchargé décompressé, on copie le dossier glm dans le répertoire d'en-têtes du compilateur.
Une fois GLM installé et prêt à l'usage, on passe au codage.
III. Code▲
III-A. main.h▲
La première chose à faire pour utiliser GLM dans une application OpenGL est d'inclure les fichiers d'en-tête correspondants. On ouvre donc main.h et on ajoute les lignes suivantes en début de fichier :
// GLM include files
#include
<glm/glm.hpp>
#include
<glm/gtc/matrix_projection.hpp>
#include
<glm/gtc/matrix_transform.hpp>
On peut maintenant utiliser les fonctions de GLM, dans l'espace de noms glm. On peut les appeler avec glm::fonction ou, après avoir ajouté la ligne suivante, avec fonction.
using
namespace
glm;
III-B. opengl_3.h▲
On définit ensuite les variables qui contiendront les matrices. Dans la section privée de opengl_3.h, on crée trois variables, une par matrice.
glm::
mat4 projectionMatrix; // Matrice de projection
glm::
mat4 viewMatrix; // Matrice de vue
glm::
mat4 modelMatrix; // Matrice de modèle
Dans ces trois matrices, une seule devra être gardée cohérente tout au long de l'application : projectionMatrix. Évidemment, on peut la changer pour créer un effet spécial.
III-C. opengl_3.cpp▲
Dans la méthode setupScene, dans opengl_3.cpp, on crée cette matrice projectionMatrix à l'aide de la méthode glm::perspective, qui fonctionne presque exactement comme gluPerspective. On doit lui donner un champ de vision (fov, field of view) en degrés, le ration d'aspect de la fenêtre et les plans proche et lointain de la scène. Pour ce faire, on ajoute la ligne suivante :
projectionMatrix =
glm::
perspective(60.0
f, (float
)windowWidth /
(float
)windowHeight, 0.1
f, 100.
f); // On crée la matrice de projection
Ceci n'est pas si effrayant, le reste sera heureusement du même acabit. On termine ainsi de modifier cette fonction puis on modifiera le vertex shader. La première chose à faire est de vider les tampons de couleur, de profondeur et de pochoir, en définissant les matrices de vue et de modèle. On veut que la matrice de vue soit une translation de cinq unités en arrière dans la scène, soit l'équivalent de glTranslate(0, 0, -5). On n'a pas de géométrie pour le moment, on se limitera donc à une mise à l'échelle.
viewMatrix =
glm::
translate(glm::
mat4(1.0
f), glm::
vec3(0.0
f, 0.0
f, -
5.
f)); // On crée la matrice de vue avec une translation en arrière de cinq unités
modelMatrix =
glm::
scale(glm::
mat4(1.0
f), glm::
vec3(0.5
f)); // On crée la matrice de modèle qui donnera la moitié de la taille du modèle
Après les avoir créées, on utilise ces matrices en les envoyant au shader qui les utilisera. Dans le code, on commence par lier ledit shader, comme dans les tutoriels GLSL. On doit mettre un lien vers ces matrices dans le shader.
int
projectionMatrixLocation =
glGetUniformLocation(shader->
id(), "projectionMatrix"
); // Récupérer la localisation de la matrice de projection dans le shader
int
viewMatrixLocation =
glGetUniformLocation(shader->
id(), "viewMatrix"
); // Récupérer la localisation de la matrice de vue dans le shader
int
modelMatrixLocation =
glGetUniformLocation(shader->
id(), "modelMatrix"
); // Récupérer la localisation de la matrice de modèle dans le shader
Une fois ces localisations stockées, on peut aller de l'avant et les envoyer avec glUniformMatrix4fv, comme dans les versions précédentes d'OpenGL. GLM autorise l'accès aux matrices de manière simple, on ajoute donc le code suivant après les localisations.
glUniformMatrix4fv(projectionMatrixLocation, 1
, GL_FALSE, &
projectionMatrix[0
][0
]); // Envoyer la matrice de projection au shader
glUniformMatrix4fv(viewMatrixLocation, 1
, GL_FALSE, &
viewMatrix[0
][0
]); // Envoyer la matrice de vue au shader
glUniformMatrix4fv(modelMatrixLocation, 1
, GL_FALSE, &
modelMatrix[0
][0
]); // Envoyer la matrice de modèle au shader
III-D. shader.vert▲
On se tourne maintenant vers le vertex shader pour utiliser ces variables. On a donc besoin de trois variables de matrices, trois mat4.
uniform
mat4 projectionMatrix;
uniform
mat4 viewMatrix;
uniform
mat4 modelMatrix;
Pour les utiliser, on peut utiliser une ligne comme celle-ci :
gl_Position =
glModelViewProjectionMatrix *
gl_Vertex;
Dans le code, on utilisera plutôt celle-ci, où in_Position est l'équivalent de gl_Vertex :
gl_Position =
projectionMatrix *
viewMatrix *
modelMatrix *
vec4
(
in_Position, 1
.0
);
IV. Résultat▲
C'est tout ce qui est requis pour passer des matrices d'OpenGL 2 et précédents vers le nouveau style introduit par OpenGL 3 de gestion par le développeur. À la fin de ce tutoriel, on n'affiche toujours rien d'autre qu'une fenêtre. Dans le tutoriel suivant, on aura finalement un carré !
Les fichiers de projet Visual Studio 2010 de ce tutoriel sont disponibles au téléchargement.
Cliquez pour lire la vidéo
V. Remerciements▲
Merci à Alexandre Laurent pour son aide à la traduction et à Sébastien Germez pour sa relecture orthographique !