Tarnyko's website
Tarnyko's website
about

GTKGLArea3 disponible pour Win32 !

2013-10-13

Objectif : afficher un contexte OpenGL dans une fenêtre GTK+3 sous Windows.

gtk

Il y a quelque mois, j'ai eu besoin d'afficher une scène 3D - rendue, bien sûr, via OpenGL - dans une fenêtre GTK+3 sous Windows.

Je me souvenais bien que des bibliothèques tierces permettaient de le faire, et une petite recherche m'en a localisée deux :

Elle fournissent toutes les deux plus ou moins la même API : l'on crée un widget dédié dans lequel la scène OpenGL va s'afficher. Il y a une gestion automatique du déplacement et du redimensionnement ; cependant certaines commodités (comme la mise à l'échelle) doivent être effectuées manuellement.

À mon grand désespoir, cependant, elles ne fonctionnaient toutes deux qu'avec GTK+2...

Patchage de GtkGLArea

J'ai donc décidé d'effectuer quelques modifications au code de GtkGLArea, et voilà finalement ce que ça donne :

gtkglarea3-win32

GtkGLArea3 modifié, dans toute sa splendeur sous Windows !

Comme mon application était écrite en Vala, j'en ai profité pour écrire les VAPI, empaqueter la bibliothèque et la fournir dans mon dépôt ValaWinPKG 😉.

Bref, voici ci-dessous comment l'utiliser !

Installer et utiliser GtkGLArea3 sous Windows

Pré-requis

Si vous ne les avez pas déjà, nous allons installer le dernier Vala et ValaWinPKG pour Windows :

1) Installer GtkGLArea3

Nous lançons ValaWinPKG depuis le menu Démarrer de Windows.
Nous cochons ensuite le paquet "GtkGLArea3" et cliquons sur le bouton "Update !".

01-valawinpkg

2) Compiler un exemple "triangle"

Nous allons d'abord afficher un triangle dans un widget OpenGL.

Dans ce code source Vala, l'on remarque :

var glarea = new GLArea (attrlist);
glarea.set_size_request (100, 100);
glarea.realize.connect (on_glarea_realize_event);
glarea.draw.connect (on_glarea_draw_event);

Nous créons un objet GLArea de taille 100x100, et lui attachons 2 callbacks : realize et draw.

void on_glarea_realize_event (Widget widget)
{
    [...]

    if (glarea.make_current () == true)
    {
        [...]
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity ();
        glOrtho (0,100, 100,0, -1,1);
        glMatrixMode (GL_MODELVIEW);
    }
bool on_glarea_draw_event (Widget widget, Cairo.Context cr)
{
    [...]

    if (glarea.make_current () == true)
    {
        [...]

        // Draw simple triangle
        glBegin (GL_TRIANGLES);
        glVertex2f (10,10);      // side 1
        glVertex2f (10,90);      // side 2
        glVertex2f (90,90);      // side 3
        glEnd ();

        // Swap backbuffer to front
        glarea.swap_buffers ();  // refresh!

Notez l'appel final à glarea.swap_buffers () pour rafraîchir la scène : rien ne s'affichera sans cela.
Notez aussi que nous utilisons glarea.make_current () à la fois comme un test (le contexte est-il toujours valide ?) et une validation (c'est dans ce contexte que nous voulons dessiner !).

Compiler et exécuter l'exemple

Compilons et exécutons :

valac --pkg gtkgl-3.0 gtkglarea3-triangle.vala -o gtkglarea3-triangle.exe
gtkglarea3-triangle

02-triangle

3) Compiler un exemple "texte"

L'autre code source est moins spectaculaire, mais introduit la gestion des polices
(fournie par GtkGLArea3 par-dessus OpenGL, qui de base ne propose rien de tel) :

GLuint fontbase;
fontbase = glGenLists (128);
Pango.FontDescription fontdesc = Pango.FontDescription.from_string ("Sans 10");
Gdk.gl_use_pango_font (fontdesc, 0, 128, fontbase);

Nous créons une liste OpenGL de 128 éléments identifiée par un GLuint : ce sera notre liste de glyphes.
Nous référons ensuite à une police TrueType très commune via le composant Pango de GTK+3 : Sans (taille 10).
Finalement, nous lions les deux, ce qui enclenche un processus complexe de "glyphes-vers-textures"... et la magie peut opérér !

Il ne nous reste qu'à écrire avec :

/* Text to display */
string fonttext = "GTKGLAREA";

[...]

glColor3f (1,1,0);   // red + green == yellow
glRasterPos2f ((100-charwidth*fonttext.length)/2, (100-charheight)/2);  // center position
glListBase (fontbase);                                                  // use list of textures
glCallLists (fonttext.length, GL_UNSIGNED_BYTE, (GL.GLvoid[])fonttext); // render 'fonttext' with textures

Compiler et exécuter l'exemple

Compilons et exécutons :

valac --pkg gtkgl-3.0 gtkglarea3-text.vala -o gtkglarea3-text.exe
gtkglarea3-text

03-text

Et voilà !


Plans d'avenis

Le port Linux est toujours en chantier (la gestion des polices y est bien plus compliquée) et sortira sous peu.
Cependant, et sans en dire trop, voilà où ça en est aujourd'hui...

gtkglarea3-linux

... il me reste à corriger ces pixmaps de texte en bas à droite 😉.

(P.S.: : j'ai appris récemment que GtkGLExt avait un port GTK+3 en chantier... dommage que je sois allé si vite !)