Dorian Fevrier's blog - Mot-clé - glutJe m’appelle FEVRIER Dorian, je suis infographiste 3D passionné par mon métier, l’informatique en général, l’internet, la programmation et l’évolution de tout ce petit monde. Vous trouverez sur ce blog des tutoriaux, mes coups de cœurs, avis, etc.2024-01-02T23:48:05+01:00FEVRIER Dorianurn:md5:695d9c73474c33ce3dab043823509c4bDotclearUne introduction à l'OpenGL "Moderne" - Chapitre 2: Hello World: Le Slideshowurn:md5:fe5bc3787b579d2eba6e17db1cb5711d2010-10-23T15:34:00+02:002013-07-26T18:12:32+02:00NarannScript et codecodecompilationfrglewglutmoderneopengltraductiontuto<p><img src="https://www.fevrierdorian.com/blog/public/logos/OpenGL_logo_tn150.png" alt="OpenGL_logo_tn150.png" style="float:left; margin: 0 1em 1em 0;" title="OpenGL_logo_tn150.png, oct. 2010" height="150" width="150" />Voici la traduction du <a href="http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-2:-Hello-World:-The-Slideshow.html" hreflang="en">deuxième chapitre</a> du tutorial de <a href="http://twitter.com/jckarter" hreflang="en">Joe Groff</a>. :hehe:</p>
<p>Ici, vous allez écrire l'architecture global de votre programme, qui concerne surtout le système de fenêtrage.</p>
<p>Prenez le temps de configurer votre environnement de développement, il ne faut pas que la compilation soit une procédure rébarbative, vous allez le faire un grand nombre de fois...</p>
<p>Ce n'est pas la partie la plus intéressante mais rassurez vous, ce tutorial est assez court et vous aurez bien assez le temps de vous casser les dents sur les suivants! :baffed:</p> <h4>Une introduction à l'OpenGL "Moderne" - Chapitre 2: Hello World: Le Slideshow</h4>
<h5>Sommaire</h5>
<ul>
<li><a href="https://www.fevrierdorian.com/blog/post/2010/10/23/Une-introduction-a-l-OpenGL-Moderne-Chapitre-2-Hello-World-Le-Slideshow#les_fichiers_dentete_opengl">Les fichiers d'entete OpenGL</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2010/10/23/Une-introduction-a-l-OpenGL-Moderne-Chapitre-2-Hello-World-Le-Slideshow#mise_en_place_de_notre_fenetre_avec_glut">Mise en place de notre fenêtre avec GLUT</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2010/10/23/Une-introduction-a-l-OpenGL-Moderne-Chapitre-2-Hello-World-Le-Slideshow#compiler_et_lancer_notre_programme">Compiler et lancer notre programme</a></li>
<li><a href="https://www.fevrierdorian.com/blog/post/2010/10/23/Une-introduction-a-l-OpenGL-Moderne-Chapitre-2-Hello-World-Le-Slideshow#chapitre_suivant">Chapitre suivant</a></li>
</ul>
<p>Mise à jour: J'ai résolu les soucis que certaines personnes ont pu rencontrer, tout particulièrement ceux concernant la compilation sur Unix et Visual C++. Ce chapitre à également <a href="http://www.reddit.com/r/programming/comments/biw8t/an_intro_to_modern_opengl_chapter_2_hello_world/" hreflang="en">sa page Reddit</a>.</p>
<center>:longBar:</center>
<p><a href="https://www.fevrierdorian.com/blog/post/2010/10/04/Une-introduction-%C3%A0-l-OpenGL-Moderne-Chapitre-1%3A-Le-Pipeline-Graphique">Dans le chapitre précédent</a>, je vous présentais un schéma <a href="https://www.fevrierdorian.com/blog/post/2010/10/04/Une-introduction-%C3%A0-l-OpenGL-Moderne-Chapitre-1%3A-Le-Pipeline-Graphique#le_pipeline_graphique">du pipeline graphique</a>. C'est l'heure de le mettre en pratique. Avant que nous essayions rendre une scène 3d, je vais faire comme dans tout bon tutorial, à savoir, une simple application "hello world" en deux dimension, afin de présenter les bases de l'API OpenGL.</p>
<p>Nous allons prendre cette image:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_08_02_OpenGL_Modern_Translate/gl2-hello-1.png" alt="gl2-hello-1.png" style="display:block; margin:0 auto;" title="gl2-hello-1.png, oct. 2010" height="300" width="400" /></p>
<p>Nous allons ensuite la dessiner dans une fenêtre.</p>
<p>Mais les images qui ne bougent pas, c'est un peu ennuyeux. C'est pourquoi nous allons rendre l'exercice un peu plus intéressant en faisant des fondus enchainés avec cette image:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_08_02_OpenGL_Modern_Translate/gl2-hello-2.png" alt="gl2-hello-2.png" style="display:block; margin:0 auto;" title="gl2-hello-2.png, oct. 2010" height="300" width="400" /></p>
<p>Ce n'est certes pas très passionnant comme programme, mais au delà de sa simplicité, celui ci nous exercera à quasiment toutes les parties d'OpenGL qu'un programme plus complexe nécessiterai.</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_08_02_OpenGL_Modern_Translate/github-logo_128.png" alt="github-logo_128.png" style="display:block; margin:0 auto;" title="github-logo_128.png, oct. 2010" height="128" width="128" /></p>
<center><i>Octocat: La mascotte de Github</i></center>
<p>Le code source complet est en ligne sur Github, <a href="http://github.com/jckarter/hello-gl" hreflang="en">ici</a>. Composé de 380 lignes de C et de deux shaders d'une douzaine de ligne chacun, ce code (qui ne fait que dessiner une image sur l'écran) peut sembler exagéré. Cela dis, une grande partie de ce code pose les bases des démos à venir.</p>
<p>Le fichier <a href="http://github.com/jckarter/hello-gl/blob/master/hello-gl.c" hreflang="en">hello-gl.c</a> contient tout ce qui concerne le rendu OpenGL, tandis que <a href="http://github.com/jckarter/hello-gl/blob/master/util.c" hreflang="en">util.c</a> contient les fonctions qui vont nous permettre de lire des images TGA.</p>
<p>J'ai inclus les deux images, hello1.tga et hello2.tga, dans ce format, car il est facile à "décoder" sans avoir à utiliser une librairie externe.</p>
<p>Les codes des shaders sont dans deux fichiers:</p>
<ul>
<li><a href="http://github.com/jckarter/hello-gl/blob/master/hello-gl.v.glsl" hreflang="en">hello-gl.v.glsl</a> pour le vertex shader.</li>
<li><a href="http://github.com/jckarter/hello-gl/blob/master/hello-gl.f.glsl" hreflang="en">hello-gl.f.glsl</a> pour le fragment shader.</li>
</ul>
<p>Dans ce chapitre, j'expliquerai comment les différentes parties du programme hello-gl utilise l'API OpenGL pour envoyer des données dans le pipeline graphique et comment il le fait fonctionner.</p>
<p>Je donnerai également un bref aperçu du <a href="https://secure.wikimedia.org/wikipedia/en/wiki/GLSL" hreflang="en">langage GLSL</a> quand nous verront shaders.</p>
<p>C'est beaucoup de choses à faire dans un seul billet de blog, c'est pourquoi je diviserai ce chapitre en quatre parties.</p>
<p>Dans cette première partie, nous allons ouvrir une fenêtre avec <a href="http://www.opengl.org/resources/libraries/glut/" hreflang="en">GLUT</a>. Dans la seconde partie, nous allons implémenter le buffer et les textures qui contiendront respectivement les vertices bruts et les images de notre programme.</p>
<p>Après ça, nous écriront le code des shaders qui traiteront ces données pour en faire l'image final, et nous les implémenterons dans notre application OpenGL.</p>
<p>Dans le dernier article, nous parlerons des appels aux fonctions OpenGL qui servent à rendre la scène sur l'écran.</p>
<p>Maintenant que vous avez le plan en tête, commençons à coder!</p>
<p>Nous allons commencer par configurer GLUT pour avoir une fenêtre vide sur l'écran.</p>
<center>:longBar:</center>
<h5>Les fichiers d'entete OpenGL <a name="les_fichiers_dentete_opengl"></a></h5>
<pre class="c c"><span style="color: #339933;">#include <stdlib.h></span>
<span style="color: #339933;">#include <GL/glew.h></span>
<span style="color: #339933;">#ifdef __APPLE__</span>
<span style="color: #339933;"># include <GLUT/glut.h></span>
<span style="color: #339933;">#else</span>
<span style="color: #339933;"># include <GL/glut.h></span>
<span style="color: #339933;">#endif</span></pre>
<p>Chaque plateforme a ses headers OpenGL à différents endroits, mais avec GLEW, vous n'avez pas à vous soucier de ça.</p>
<p>Le fait d'inclure GL/glew.h vous permet de récupérer tout les headers OpenGL, sans que vous ayez à aller les récupérer vous même.</p>
<p>Malheureusement, ce n'est pas le cas de GLUT, et pour l'inclure, vous devez passer par quelques tricks multi-plateforme (les ifdef).</p>
<p>Son header est généralement dans GL/glut.h, mais le framework GLUT livré avec MacOS X utilise les conventions de header Apple. Ducoup, le header de GLUT est dans GLUT/glut.h.</p>
<p>Il y a également un bug dans la façon dont les versions récentes des headers C standards de Visual Studio interagissent avec glut.h, ce qui requière que stdlib.h soit déclaré avant glut.h.</p>
<center>:longBar:</center>
<h5>Mise en place de notre fenêtre avec GLUT <a name="mise_en_place_de_notre_fenetre_avec_glut"></a></h5>
<pre class="c c"><span style="color: #993333;">int</span> main<span style="color: #009900;">(</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span><span style="color: #339933;">**</span> argv<span style="color: #009900;">)</span>
<span style="color: #009900;">{</span>
glutInit<span style="color: #009900;">(</span><span style="color: #339933;">&</span>argc<span style="color: #339933;">,</span> argv<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
glutInitDisplayMode<span style="color: #009900;">(</span>GLUT_RGB <span style="color: #339933;">|</span> GLUT_DOUBLE<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
glutInitWindowSize<span style="color: #009900;">(</span><span style="color: #0000dd;">400</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">300</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
glutCreateWindow<span style="color: #009900;">(</span><span style="color: #ff0000;">"Hello World"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
glutDisplayFunc<span style="color: #009900;">(</span><span style="color: #339933;">&</span>render<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
glutIdleFunc<span style="color: #009900;">(</span><span style="color: #339933;">&</span>update_fade_factor<span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
<p>GLUT fournit une interface au système de fenêtrage (window system) limité mais simple et portable.</p>
<p>Après avoir initialisé GLUT en appelant la fonction glutInit, nous utilisons glutInitDisplayMode pour spécifier les buffers dont notre framebuffer par défaut disposera.</p>
<p>Dans notre cas, un buffer de couleur (GLUT_RGB) avec double buffering (GLUT_DOUBLE) est suffisant.</p>
<p><a href="http://en.wikipedia.org/wiki/Double_buffering#Double_buffering_in_computer_graphics" hreflang="en">La technique du double buffering</a> permet de stocker deux color buffers dans le framebuffer et d'alterner à chaque frame entre le buffer affiché sur l'écran et celui qui est en court de rendu, ce qui permet d'avoir une animation fluide.</p>
<p>Si nous avons besoin d'un buffer de profondeur (depth buffer) ou d'un buffer de masque (stencil buffer), nous pouvons l'appeler ici.</p>
<p>Ensuite, nous nous servons de glutInitWindowSize pour initialiser la taille de notre fenêtre à 400x300 (la taille de nos images) et nous créons notre fenêtre avec glutCreateWindow.</p>
<p>Pour finir, nous faisons appel à deux fonctions qui "reçoivent" les events (callbacks) de la fenêtre:</p>
<ul>
<li>glutDisplayFunc qui calcul notre image quand la fenêtre lui demande de s'afficher.</li>
<li>glutIdleFunc qui met continuellement à jour le "fade factor" entre les deux images.</li>
</ul>
<pre class="c c">glewInit<span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">(</span><span style="color: #339933;">!</span>GLEW_VERSION_2_0<span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
fprintf<span style="color: #009900;">(</span>stderr<span style="color: #339933;">,</span> <span style="color: #ff0000;">"OpenGL 2.0 not available<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span></pre>
<p>Une fois que GLUT a créé notre fenêtre, nous préparons OpenGL afin de pouvoir y faire des appels.</p>
<p>La première chose que nous faisons est d'initialiser GLEW. Lorsque glewInit est appelé, il définit des appels au fonctions OpenGL en se basant sur la version ainsi que les extensions supportées par votre matériel.</p>
<p>Nous vérifions que GLEW_VERSION_2_0 est définit pour être certain que le matériel qui exécuté le programme a au moins OpenGL 2.0.</p>
<p>Une fois que la version est vérifié, l'utilisation de GLEW devient quasiment invisible, et nous n'aurons plus besoin d'interagir avec lui.</p>
<pre class="c c"><span style="color: #b1b100;">if</span> <span style="color: #009900;">(</span><span style="color: #339933;">!</span>make_resources<span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
fprintf<span style="color: #009900;">(</span>stderr<span style="color: #339933;">,</span> <span style="color: #ff0000;">"Failed to load resources<span style="color: #000099; font-weight: bold;">\n</span>"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>
glutMainLoop<span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span></pre>
<p>GLEW initialisé, nous appelons notre fonction make_resources qui set nos ressources OpenGL.</p>
<p>Nous verront cette fonction durant les prochaines parties de ce chapitre.</p>
<p>Si nos ressources sont correctement chargé, glutMainLoop prend le relais.</p>
<p>Il affiche la fenêtre, commence par recevoir les events de l'UI, et appel les fonctions que l'on a setté en réponse à ses events (les callbacks).</p>
<p>Il fermera aussi le programme pour nous quand l'utilisateur le quittera.</p>
<p>Le return 0 supprime simplement les avertissements du compilateur et il n'est, de toute façon, jamais réellement atteint.</p>
<center>:longBar:</center>
<h5>Compiler et lancer notre programme <a name="compiler_et_lancer_notre_programme"></a></h5>
<p>Arrivé ici, nous pouvons écrire le code des callbacks de GLUT, de la fonction make_resources, et faire fonctionner notre (au combien inutile) programme.</p>
<pre class="c c"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> make_resources<span style="color: #009900;">(</span><span style="color: #993333;">void</span><span style="color: #009900;">)</span>
<span style="color: #009900;">{</span>
<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span></pre>
<pre class="c c"><span style="color: #993333;">static</span> <span style="color: #993333;">void</span> update_fade_factor<span style="color: #009900;">(</span><span style="color: #993333;">void</span><span style="color: #009900;">)</span>
<span style="color: #009900;">{</span>
<span style="color: #009900;">}</span></pre>
<pre class="c c"><span style="color: #993333;">static</span> <span style="color: #993333;">void</span> render<span style="color: #009900;">(</span><span style="color: #993333;">void</span><span style="color: #009900;">)</span>
<span style="color: #009900;">{</span>
glClearColor<span style="color: #009900;">(</span><span style="color:#800080;">1.0f</span><span style="color: #339933;">,</span> <span style="color:#800080;">1.0f</span><span style="color: #339933;">,</span> <span style="color:#800080;">1.0f</span><span style="color: #339933;">,</span> <span style="color:#800080;">1.0f</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
glClear<span style="color: #009900;">(</span>GL_COLOR_BUFFER_BIT<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
glutSwapBuffers<span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span></pre>
<p>glClearColor set une couleur de fond <a href="https://secure.wikimedia.org/wikipedia/fr/wiki/RGBA" hreflang="fr">RGBA</a> (dans notre cas, blanche) que glClear utilise pour remplir le buffer de color du framebuffer.</p>
<p>glutSwapBuffers amène ensuite notre color buffer à l'écran.</p>
<p>Avec tout ça en place, nous pouvons maintenant compiler et lancer notre programme.</p>
<p>Cette version est dans le reposit de Github et s'appelle <a href="http://github.com/jckarter/hello-gl/blob/master/hello-gl-dummy.c" hreflang="en">hello-gl-dummy.c</a>.</p>
<p>La commande qui compile le programme et le link aux libs OpenGL, GLUT et GLEW peut varier suivant les plateformes.</p>
<p>Sur la plupart des systèmes Unix, elle devrait ressembler à ça:</p>
<pre class="bash bash"><span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-o</span> hello-gl-dummy hello-gl-dummy.c \
-I<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>X11R6<span style="color: #000000; font-weight: bold;">/</span>include -L<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>X11R6<span style="color: #000000; font-weight: bold;">/</span>lib \
<span style="color: #660033;">-lGL</span> <span style="color: #660033;">-lGLEW</span> <span style="color: #660033;">-lglut</span></pre>
<p>Sur MacOS X:</p>
<pre class="bash bash"><span style="color: #666666; font-style: italic;"># Assuming GLEW was installed to /opt/local</span>
<span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-o</span> hello-gl-dummy hello-gl-dummy.c \
-I<span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>include -L<span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>lib \
<span style="color: #660033;">-framework</span> OpenGL <span style="color: #660033;">-framework</span> GLUT <span style="color: #660033;">-lGLEW</span></pre>
<p>Sur Windows avec Visual C++:</p>
<pre class="bash bash">cl <span style="color: #000000; font-weight: bold;">/</span>Fohello-gl-dummy.obj <span style="color: #000000; font-weight: bold;">/</span>c hello-gl-dummy.c
<span style="color: #c20cb9; font-weight: bold;">link</span> <span style="color: #000000; font-weight: bold;">/</span>out:hello-gl-dummy.exe hello-gl-dummy.obj \
opengl32.lib glut32.lib glew32.lib</pre>
<p>Sur Windows avec mingw:</p>
<pre class="bash bash"><span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-o</span> hello-gl-dummy.exe hello-gl-dummy.c \
<span style="color: #660033;">-lopengl32</span> <span style="color: #660033;">-lglut32</span> <span style="color: #660033;">-lglew32</span></pre>
<p>Le reposit contient également les makefiles de chacune de ses plateformes.</p>
<p>Vous pouvez compiler cette version du programme en utilisant hello-gl-dummy (ou hello-gl-dummy.exe sur Windows):</p>
<pre class="bash bash"><span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #660033;">-f</span> Makefile.MacOSX hello-gl-dummy <span style="color: #666666; font-style: italic;"># or Makefile.Unix or Makefile.Mingw</span></pre>
<pre class="bash bash">nmake <span style="color: #000000; font-weight: bold;">/</span>f Nmakefile.Windows hello-gl-dummy.exe</pre>
<p>Une fois que vous avez compilé le programme, vous devriez être capable de le lancer et d'avoir une fenetre blanche, comme promis:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/2010_08_02_OpenGL_Modern_Translate/gl2-dummy-screenshot.png" alt="gl2-dummy-screenshot.png" style="display:block; margin:0 auto;" title="gl2-dummy-screenshot.png, oct. 2010" height="334" width="412" /></p>
<p>Fermez la fenêtre, ou, sur MacOS X, quittez l'application.</p>
<center>:longBar:</center>
<h5>Chapitre suivant <a name="chapitre_suivant"></a></h5>
<p>Avec la satisfaction d'avoir une fenêtre ouverte devant nous, nous somme prêt à remplir OpenGL de vertex et d'images.</p>
<p>Dans le prochain article, j'introduirais les buffers et textures OpenGL.</p>
<blockquote><p>Vous pouvez retrouver l'article original sur <a href="http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-2:-Hello-World:-The-Slideshow.html" hreflang="en">la page de Joe Groff</a>, un fois de plus: Merci à lui!</p></blockquote>