Utilisation de glPolygonStipple

C’est parti pour le premier article technique de cette année.

Comme vous le savez j’apprends l’OpenGL avec le livre officiel dans sa septième édition. Pour le moment, je n’ai lu que 1/10ème du livre en question. Mais je dois reconnaître que ce livre regorge d’informations mais elles sont parfois trop peu approfondies. Je vais donc par le biais de ce post vous présenter la fonction glPolygonStipple qui vous permettra d’appliquer des textures sur différentes surfaces.

Pour faire simple, j’ai opté pour un dessin simple: un smiley. Le but de cet article va donc être d’appliquer une texture sur une surface 2D classique: glRectf.

Mais avant de nous jeter dans le code, il faut tout d’abord savoir ce que va faire notre programme :

  1. Initialisation d’OpenGL et définition du repère de travail
  2. Création d’un tableau de byte représentant notre smiley
  3. Appliquer notre smile sur un glRectf

Pour ce qui est de la première étape d’initialisation d’OpenGL et du repère, il suffit de saisir les lignes suivantes :

/*Define the drawing zone properties*/
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glViewport(0, 0, 10, 10);

//Load identity matrix
glLoadIdentity();

//Define x & y axis
gluOrtho2D((GLdouble) -10, (GLdouble) 10, (GLdouble) -10, (GLdouble) 10);
}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(1024,100);
glutCreateWindow("OpenGL GLubyte Demo");

init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}

Voilà, ce code est assez classique rien d’extraordinaire à expliquer et puis je l’ai déjà fait dans un post précédent. Nous allons pouvoir directement passer à la seconde étape, celle qui nous intéresse le plus: la création du smiley.

Pour ma part, j’utilise un tableur comme celui d’OpenOffice.org pour modéliser le smiley et en faire le découpage en tableau de bytes.

Faîtes une grille de 32×32 soit 1024 cases. Arrangez-vous pour ne pas faire des cases trop grandes et de forme carrée pour que cela tienne sur votre écran (bon effectivement si vous avez un 14″ ça va être dur … :p). Une fois les cases dessinées faites des bordures plus épaisses sur des rectangles de 8×4 (Longueur x Hauteur) pour avoir 4 colonnes (si si je vous assure 4×8 ça fait 32). Pour dessiner notre smiley, il suffit de noircir les cases de la grille pour que l’ensemble ressemble à un smiley.

Comme je suis sympa, vous pouvez prendre mon modèle au format ODS ici.

Vous devriez donc avoir un smiley ressemblant à celui-ci :

Si vous avez téléchargé mon fichier ODS, vous savez ce que nous allons faire: traduire notre smiley en byte. Mais comment faire !? J’ai eu du mal à trouver mais c’est en fait très simple. Il suffit de connaître le principe et ça se fait très vite. Zoomons sur la première partie de l’œil :

Chaque case de dimension 8×4 va vous donner 4 valeurs hexadécimales (une pour chaque ligne) que nous reporterons dans un tableau. La première case de droite vaut 1, la suivante 2, puis 4 et ainsi de suite jusqu’à la dernière qui vaut 80 (128 en décimal). Ici, nous aurons donc les valeurs 0, 0, 1, 3. Je vous laisse vous entrainer avec les autres cases. Si vous avez pris le même exemple que moi, vous avez les valeurs suivantes (à partir du coin de l’œil ci-dessus): 1, 80, 1, 80, 3, C0, 3, C0, 3, C0, 3, C0, 1, 80, 1, 80, 0, 0, 80, 0, … 0, 0E, 70, 0, 0, 3, C0, 0 …

Seulement voilà, si nous utilisions ces valeurs dans notre programme nous aurions un smiley à l’envers car la fonction glPolygonStipple se base sur les bits de poids forts. Ils faut donc inverser chaque groupe de 4 valeurs (les lignes de notre grille) et nous pourrons retourner à notre code. Les valeurs seront donc les suivantes : 0, 3, C0, 0, 0, 0E, 70, 0, …, 0, 0, 80, 0, 1, 80, 1, 80, 3, C0, 3, C0, 3, C0, 3, C0, 1, 80, 1, 80 …

Le plus gros du travail est maintenant terminé, il nous reste à écrire notre fonction display() :

/*Display function*/
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1.0, 1.0, 1.0);

    //Our values from the previous step
    GLubyte smile[] = {
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x03, 0xC0, 0x00,
        0x00, 0x0E, 0x70, 0x00,
        0x00, 0x18, 0x18, 0x00,
        0x00, 0x20, 0x04, 0x00,
        0x00, 0x40, 0x02, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x02, 0x00, 0x00,
        0x00, 0x01, 0x00, 0x00,
        0x00, 0x01, 0x00, 0x00,
        0x00, 0x01, 0x00, 0x00,
        0x00, 0x01, 0x00, 0x00,
        0x00, 0x01, 0x00, 0x00,
        0x00, 0x00, 0xC0, 0x00,
        0x01, 0x80, 0x01, 0x80,
        0x03, 0xC0, 0x03, 0xC0,
        0x03, 0xC0, 0x03, 0xC0,
        0x01, 0x80, 0x01, 0x80,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00
    };

    glEnable(GL_POLYGON_STIPPLE);

    glPolygonStipple(smile);
    //Define the surface where we apply our texture
    glRectf(10, -10, -10, 10);

    glDisable(GL_POLYGON_STIPPLE);
    glFinish();
}

C’est ici que l’on se rend vraiment compte de l’intérêt du fonctionnement interne d’OpenGL comme une machine à états. La fonction glEnable() permet d’activer GL_POLYGON_STIPPLE en mémoire, d’exécuter la fonction glPolygonStipple() avec les valeurs obtenues à l’étape précédente, d’appliquer notre « tapisserie » sur le glRectf. Une fois que l’on en a plus besoin, on désactive GL_POLYGON_STIPPLE ce qui permet de vraiment optimiser les traitements et la mémoire.

Et voilà, c’est fini ! Vous pouvez compiler votre code est admirer votre travail :

J’espère que cette première partie vous a plu.

A bientôt pour opengellesques aventures ;-) .

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>