Developpez.com - Rubrique Qt

Le Club des Développeurs et IT Pro

En direct des Qt DevDays 2012

Détails techniques sur l'utilisation d'OpenGL moderne dans Qt 5

Le 2012-11-13 10:40:04, par LittleWhite, Responsable 2D/3D/Jeux
Il est vrai qu'hier je n'ai pas donné beaucoup d'informations techniques. Maintenant que j'ai un peu plus de temps, je peux vous expliquer les nouveautés dans la création d'applications OpenGL de Qt 5.

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 :
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);

    ...
(Note : QWindow hérite de QSurface)

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 :
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 );
Une fois le format configuré, il faut l'indiquer au QOpenGLContext :
Code :
1
2
3
4
// Créer un contexte OpenGL
m_context = new QOpenGLContext;
m_context->setFormat( format );
m_context->create();
Le contexte doit par la suite être passé à une scène (classe héritant de QAbstractScene).

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 :
m_context->makeCurrent(this);
(makeCurrent() accepte un paramètre de type pointeur sur QSurface).

(Note : un contexte ne peut être actif que dans un thread à la fois)

Pour l'affichage, nous pouvons imaginer le code suivant :
Code :
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 );
}
Par défaut, Qt utilise du double buffering.

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
  Discussion forum
14 commentaires
  • froggy25
    Membre à l'essai
    Merci pour ces compte-rendus, bon boulot

    *a de la lecture*