Initialisation d'OpenGL dans Qt 5
Tout d'abord, si vous voulez faire une fenêtre utilisant OpenGL, vous n'avez plus besoin d'hériter votre classe de QGLWidget mais simplement de la nouvelle classe QWindow (qui remplace QWidget). Lors de sa construction, vous devriez appeler la fonction setSurfaceType() avec comme paramètre OpenGLSurface afin d'avoir une fenêtre OpenGL. Voici l'exemple d'une classe Window qui hérite de QWindow afin de mettre en place une fenêtre OpenGL :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 | Window::Window( QScreen* screen ) : QWindow( screen ) { // Indique à Qt que nous allons utiliser OpenGL avec cette fenêtre setSurfaceType(OpenGLSurface); ... |
Toutefois, nous n'avons pas encore configuré OpenGL. Pour cela, nous utilisons deux classes :
- QSurfaceFormat
- QOpenGLContext
Sean Harmer compare QSurfaceFormat à un papier et QOpenGLContext à un crayon.
Plus précisément, QSurfaceFormat permet de définir la version d'OpenGL (setMajorVersion() et setMinorVersion()), le profile (core ou deprecated) à utiliser (setProtile()), mais aussi le niveau de multisampling (anti-aliasing), la taille du buffer de profondeur, ...
Code : | Sélectionner tout |
1 2 3 4 5 6 7 | // Spécifie le format que nous voulons QSurfaceFormat format; format.setDepthBufferSize( 24 ); format.setMajorVersion( 3 ); format.setMinorVersion( 3 ); format.setSamples( 4 ); format.setProfile( QSurfaceFormat::CoreProfile ); |
Code : | Sélectionner tout |
1 2 3 4 | // Créer un contexte OpenGL m_context = new QOpenGLContext; m_context->setFormat( format ); m_context->create(); |
Chaque fois que vous devez agir sur ce contexte OpenGL (initialisation d'OpenGL, mis à jour des buffers, affichage, ...) il faut rendre le context actif :
Code : | Sélectionner tout |
m_context->makeCurrent(this);
(Note : un contexte ne peut être actif que dans un thread à la fois)
Pour l'affichage, nous pouvons imaginer le code suivant :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | void Window::paintGL() { // Rend le contexte actif m_context->makeCurrent( this ); // Effectue le rendu (dans le back buffer) m_scene->render(); // Échange les front/back buffers m_context->swapBuffers( this ); } |
Gestion des extensions
La gestion a changé dans cette nouvelle version de Qt. Tout d'abord, la classe QOpenGLContext vous permet de récupérer une liste d'extensions sous la forme d'un QSet<QByteArray> avec la méthode extensions(). De plus, cette même classe intègre une seconde fonction : hasExtension() qui retourne un boolean indiquant si l'extension est supportée par la machine ou non.
Bien sur, la fonction getProcAddress() permettant de récupérer les pointeurs de fonctions sur les fonctions des extensions OpenGL est toujours présente. Mais son usage a été limité car elle était source de problèmes. Pour remplacer cet ancien mécanisme, la classe QOpenGLContext expose une fonction functions() qui retourne un QOpenGLFunctions*. Cette dernière contient des méthodes pour appeler les fonctions OpenGL.
Par contre, OpenGLFunctions ne fournit pas toutes les fonctions disponibles dans OpenGL (surtout si une nouvelle spécification OpenGL est créée), ni les fonctions pour toutes les extensions.
De plus, Qt 5 propose des factory de fonctions appelées QOpenGLVersionFunctionsFactory (implémenté sous la forme d'un singleton). Cette classe aurait dû être intégrée directement dans QOpenGLContext, mais elle n'était pas prête pour Qt 5.0. Elle le sera dans Qt 5.1.
L'avantage est que la classe ajoute des vérifications au moment de la compilation.
Le code d'exemple utilisé pendant la formation est disponible : http://qt.developpez.com/evenement/2.../dd-opengl.zip