Listes d'affichage - (Display Lists)


Préalables
Pour ce tutoriel, vous aurez besion du composant [SetupGL].
Survol du tutoriel
  • Qu'est-ce qu'une liste d'affichage
  • À quoi servent plus précisément les listes d'affichage
Qu'est-ce qu'une liste d'affichage
Une liste d'affichage permet d'améliorer les performances de votre application dans la mesure ou il est possible d'y stocker une ou plusieurs commandes d'OpenGL et de les rappeler par UNE simple commandes. Le principe est assez simple, on demande à OpenGL de nous donner un numéro d'autorisation pour la nouvelle liste et une fois ce numéro récupérer alors nous stockons les commandes à l'intérieurs de ces deux clauses que voici :

 {Commencement de la nouvelle liste d'affichage}
 glNewList( LaListe, GL_COMPILE );
 
 {C'est ici que l'on conçoit ce que l'on veut que la liste contienne}
 
 {Fin de la liste}
 glEndList();

Les commandes y étant stockées peuvent être par exemple :
  • Des formes géométriques (Primitives)
  • Rotations, translations et redimensionnement...
  • Ou encore une partie d'une scène ou une scène entière.
  • Référez vous à l'aide en ligne sur ces deux commandes, car certainnes commandes OpenGL n'y sont pas admise...
À quoi servent plus précisément les listes d'affichage
Quand on construit un cube sommets par sommets avec les deux commandes glBegin( GL_QUADS); / glEnd();, ce code prend considérablement de la place et par ailleur il doit être recalculé à chaque rendu dans notre scène. Pour contrer ce problème, la liste d'affichage permet de créer en permanence l'objet ou l'action de votre choix et de simplement le ou la rappeler avec la commande suivante : glCallList( Numéro_de_la_liste );.

Voici un problème donné :
Vous voulez dessiner un bonhomme de neige mais vous constatez que vous devez créer trois sphères de différentes grosseurs ( À supposer aussi que GLUT n'existe pas ). Évidemment les trois sphères ont toutes de la même forme mais elles sont de dimension différentes et par la même occasion vous vous dites : " mais je n'ai pas besion de créer trois sphères car je n'ai qu'en fabriquer une et de la redimensionner avant de l'afficher ! ". Et comme dit précédemment, à supposé que GLUT n'existe pas alors il vous faudra créer la sphère avec les mathématiques et cela implique le besion de se servir des fonctions Cos et Sin qui sont très gourmandes en temps machines. Cela n'aurait pas de sens de fabriquer 3 sphères à chaque fois que votre scène se redessine, ce serait trop long. La solution :

Fabriquer une fonction capable de créer une sphère avec un rayon et le nombre de méridiens et parallèles donnés. Une fois celle-ci fabriquer alors nous pourrons nous en servir pour construire le bonhomme de neige en redimensionnant la sphère en fonction de la partie du corps à dessiner.

En conclusion, il suffit que de stocker la ou les base(s) géométrieque(s) dans une liste d'affichage et y faire appel autant de fois que nécessaire. Quand vous n'aurez plus besoin de cette liste, il sera aussi possible de la supprimer, ce qui libère de la mémoire, bref... tout pour donner une chance aux performances de votre application. Mais noté qu'une fois supprimée, elle et son contenu ne seront plus en mémoire, mais par contre l'index prise par celle-ci sera maintenant réutilisable pour la création d'une nouvelle liste au besoin.

Voyons voir comment créer une liste d'affichage :

  1. Demander à OpenGL d'attribuer(Générer) un index à notre liste d'affichage avec la commande suivante : glGenList(...);
  2. Créer la liste en se servant des ces deux commandes : glNewList( GLuint list, GLenum mode ); / glEndList();
  3. Une fois l'utilisation terminée (Souvent à la fermeture du programme) alors on supprime la liste avec la commande : glDeleteList(...);


Voici un exemple simple :
procedure TFrmOpenGL.SetupGLInit(Sender: TObject);
Begin
    ...
    glClearColor( 0, 0, 0, 1 );
    glEnable( GL_DEPTH_TEST );

    Sphere := glGenLists( 1 );
    glNewList( Sphere, GL_COMPILE );
        CreerSphere( 30, 30, 5.0 );
    glEndList();
	...
End;

Procedure TFrmOpenGL.CreerSphere( Const NbParalleles :GLint;
                                  Const NbMeridiens :GLint;
                                  Const Rayon :GLdouble );
Const
     DOUBLE_PI = 2 * PI;
Var
   I, J          :Integer;
   Theta,Theta2  :GLfloat;
   Phi           :GLfloat;
   Vx, Vy, Vz    :GLdouble;
begin
     glPushMatrix();
     For I := 0 To NbParalleles  Do
     Begin
          glBegin( GL_TRIANGLE_STRIP );

          Theta  := I       * DOUBLE_PI / NbParalleles;
          Theta2 := (I + 1) * DOUBLE_PI / NbParalleles;
          For J := 0 To NbMeridiens Do
          Begin
               Phi  := J * DOUBLE_PI / NbMeridiens;

               Vx := Cos(Theta) * Cos(Phi);
               Vy := Cos(Theta) * Sin(Phi);
               Vz := Sin(Theta);
               glNormal3f( Vx, Vy, Vz );
               glVertex3d( Rayon * Vx, Rayon * Vy, Rayon * Vz );

               Vx := Cos(Theta2) * Cos(Phi);
               Vy := Cos(Theta2) * Sin(Phi);
               Vz := Sin(Theta2);
               glNormal3f( Vx, Vy, Vz );
               glVertex3d( Rayon * Vx, Rayon * Vy, Rayon * Vz );

          End;
          glEnd();
     End;
     glPopMatrix;
End;


procedure TFrmOpenGL.SetupGLDraw(Sender: TObject);
Begin
     glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT);
     glClearColor( 0.0, 0.0, 0.0, 1.0 );

     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity;

     glTranslated( 0.0, 0.0, -20.0 );
     glCallList( Sphere );

     SwapBuffers( Canvas.Handle );
End;

Explication de l'exemple
C'est loin d'être un exemple complet mais j'ai juste inclu les points importants pour se servir d'une liste d'affichage. Vous y verrez plus clair dans l'exemple livrée avec ce tutorial dans le bas de la page.

glGenLists(1);
On demande à OpenGL de générer un nombre listes en mémoire, ici on lui à passé 1 en paramètre donc une liste sera générée. Cette commande retourne un indice qui sera attribuer notre liste. Si glGenLists retourne 0 alors c'est qu'OpenGL n'a pu créer la liste, soit par manque de mémoire ou parce que toutes les indices sont déjà prises.

glNewList( Boule, GL_COMPILE ); / glEndList();
Le premier paramètre spécifie l'index de la liste. Donc une variable de type entier non-signé qui contient l'indice de la liste précédemment récupérer avec la commande glGenList(...).
Le deuxième paramètre spécifie le mode de compilation. GL_COMPILE ou GL_COMPILE_AND_EXECUTE. La différence entre ces deux paramètres est la suivante : Si vous utilisez GL_COMPILE alors la liste d'affichage est compilé et prêt à être utilisée, en revanche si vous utilisez le mode GL_COMPILE_AND_EXECUTE alors la liste peut être utilisée lors de sa compilation.
Toutes les commandes, appel de fonctions ou procédures... se trouvant à l'intérieur de ces deux commandes feront parties de la conception de la liste. Donc quand vous ferez appel à cette liste, tout ce qui était à l'intérieur aura été compilé et prêt à être utilisé.

glCallList( Sphere );
Le résultat de cette commande est de faire appel à tout ce qui à été compilé à l'intérieur de la liste d'affichage, par conséquent dans ce cas-ci, se sera notre sphère qui sera dessinée.
Son seul paramètre est l'index de la liste d'affichage, alors nous lui passons la variable Sphere. Cette variable contient l'index car elle lui à été attribué à l'aide de la commande glGenList(...)


Je ne l'ai pas mentionné, mais il est aussi possible pendant la conception d'une liste d'affichage de faire appel à d'autres listes d'affichage selon le besion.

Et maintenant voici l'exemple concernant les listes d'affichage :

Capture d'écran

Programme relié
Hmmm! Cette horloge est entièment fait avec la même sphère. Tout un défi ! L'exemple n'est pas des plus faciles mais je vous conseil fortement de l'étudier et ensuite vous devriez très bien maîtriser les listes d'affichage.

  Source


Retour