OpenGL

Open GL (Open Graphics Library) est un sous ensemble de Iris GL, développé par Silicon Graphics Inc. vers la fin des années 80 pour le rendu graphique sur les stations de travail tournants sur des sous système d’exploitation IRIX (eux même sous-système d’UNIX).

Il intègre initialement des concepts propres à UNIX et Xwindow (architecture client-serveur, sockets).

Initialement conçu pour afficher des objets en 3D colorés dans des logiciels de CAO. Prendra un tournant vers le jeu vidéo dans les années 2000, et le calcul parallèle dans les années 2020.

Il est en concurrence avec Direct3D de Microsoft (Direct X), ou encore des API graphiques propriétaires de Sony et Nintendo spécialisées pour leur machines, et Metal sur les machines Apple.

Jusqu’à la version 10.14 de macOS (2018) était la norme sur Macinstosh, après quoi l’interface Metal la remplace. Metal permet d’accéder à toute la puissance des GPU Silicon d’Apple et à ses puces de Machine Learning .

Sur Windows, les fabricants de carte graphique collaborent avec Microsoft pour que DirectX puisse accéder aux dernières évolutions matérielles. DirectX est donc recommandé si l’on souhaite fabriquer des jeux vidéo à la pointe de la technologie.

Sur les autres systèmes UNIX (Linux) elle est toujours la norme. OpenGL est aussi la base de WebGL 🌍⤴ .

Contrairement a Vulkan, Metal et aux API specifiques à certaines machines, OpenGL est une API de haut niveau qui décrit des formes géométriques et des transformations s’appliquant dessus. Pour gagner en performance elle tend à intégrer des notions de bas niveau et à augmenter sa complexité au fur et à mesure qu’elle évolue. OpenGL ne permet pas de manipuler directement le GPU par exemple comme le ferait Mantle, Vulkan ou Metal.

Là où dessiner une simple forme géométrique à l’écran ne prenait qu’une dizaine de lignes de codes en OpenGL 1, il en faut presque une centaine voir plusieurs centaines dans les versions “performantes” et récentes d’OpenGL.

Historique

La version 1.0 (1992) fonctionne en mode immédiat et orienté pour les logiciels de CAO.

La version 1.1 (1997) apporte un systeme avancé de gestion de textures, tournant vers le jeu vidéo.

La version 1.5 (2003) apporte les VBO et le mode retenu (retained mode), plus performant que le mode immédiat (immediate mode).

La version 2.0 (2004) apporte les shaders avec le langage GLSL et le mode programmable.

La version 3.0 (2008) apporte un mécanisme de déprécation et de retrait d’anciennes fonctionnalités d’OpenGL.

La version 4.0 (2010) essaye d’être à la parité de fonctionnalité avec Direct3D (DirectX)

Vulkan (2016), OpenGL 5 ? Enlève tous les idiomes ancestraux d’OpenGL et repart sur une nouvelle base inspirée de Mantle. Les nouvelles fonctionnalités des cartes graphiques sont rendues accessible en priorité dans Vulkan.

Livres publics

Livre bien fait : https://openglbook.com 🌍⤴

Shaders : https://thebookofshaders.com 🌍⤴

Cours tiers

OpenGL 1.0

OpenGL 3.3 >

Normes

Utile

Fonctions de l’api selon versions http://web.eecs.umich.edu/~sugih/courses/eecs487/common/notes/APITables.xml 🌍⤴

Open GL 1

Crée à la fin des années 80, normé au début des années 90. Utilise le paradigme Start/End, avec quelques optimisations, par exemple écrire

glRect(x1, x2, y1, y2);

correspond au code suivant

glBegin(POLYGON);
    glVertex(x1, y1);
    glVertex(x2, y1);
    glVertex(x2, y2);
    glVertex(x1, y2);
glEnd();

Les Display List permettent de stocker des suites de commandes client sur le serveur pour les repeter à l’envie.

Utilise la notion de client-serveur, séparant l’état du client avec l’état du serveur. Avant la création des cartes graphiques dans les années 90, des stations de travail graphique étaient chargés de produire les images et les distribuer à des stations de travail réceptrices.

Aujourd’hui dans le vocabulaire OpenGL, le serveur désigne le GPU, tandis que le client est le CPU. Une commande OpenGL est envoyee par le CPU et aboutit à un résultat sur le GPU.

Pour utiliser le GPU, le CPU lui envoye des instructions à travers l’API OpenGL, qui les traduira en instructions concrètes in silico.

Lorsque Silicon Graphics décide de rendre IrisGL open source ils durent rendre l’API indépendante du système de fenêtrage utilisé. Sur les machines Unix on utilise le systeme X Window, sur Mac le système Quartz et sur Windows Win 32. Ainsi toutes les routines consistant a creer, redimensionner, deplacer les fenetres et lire les entrees clavier ou souris ont été déportées hors de OpenGL. Si on souhaite creer un contexte Open GL il faut donc utiliser les fonctions natives de chaque systeme d’exploitation : GLX pour XWindow, WGL pour Win32, CGL pour Quartz et EGL pour les systemes embarqués.

Lorsqu’on cree un contexte OpenGL on doit demander les specifications que l’on souhaite pour celui-ci : nombre de bits pour chaque couleur, presence ou non d’un stencil buffer, etc. Selon les parametres du contexte, des parties differentes de la carte graphique pourraient etre mis à contribution à chaque commande OpenGL. C’est pour cette raison que suite à la création d’un contexte, il faut demander au système d’exploitation de faire pointer les commandes OpenGL vers celles qui sont les plus pertinentes. Encore une fois cela est dependant du systeme d’exploitation et cela n’est pas couvert par OpenGL, mais il existe plusieurs librairies dites “loaders” qui s’en chargent. La plus ancienne est Glut et son fork plus recent OpenGlut puis Freeglut, ainsi que Glew et Glad. Ces fonctions doivent etre appelées après l’obtention d’un contexte OpenGL et avant tout appel à une commande OpenGl du type glViewport par exemple.

Plus de details sur l’obtention des appels de fonctions ici https://www.khronos.org/opengl/wiki/Load_OpenGL_Functions 🌍⤴

Plus d’informations sur les contextes OpenGL https://www.khronos.org/opengl/wiki/OpenGL_Context 🌍⤴

La litterature de reference pour cette version est le “red book”, accessible ici https://w2.mat.ucsb.edu/594cm/2010/docs/RedBook.pdf 🌍⤴

Beaucoup de liens utiles pour se replonger dans le monde OpenGl des années 90 et 2000 : https://web.archive.org/web/20130501085645/http://glprogramming.com/links.php 🌍⤴

Cours OpenGL de l’université du Texas : https://www.cs.utexas.edu/~fussell/courses/cs354 🌍⤴

Vertex Arrays

Dès OpenGL 1.1, au lieu de passer les vertices un par un, ainsi que leur couleurs et leur normales, il est rapidement devenu possible de passer tous les vertices en un seul bloc par le biais de “vertex arrays”.

Open GL avec VBO en mode “retenu”

Il faudra attendre OpenGL 1.5 pour voir la notion de “Vertex buffer objects”, qui sont des zones de mémoire allouées sur la carte graphique où l’on stocke nos données de vertices une fois pour toutes, sans avoir besoin de les repasser à la carte graphique à chaque “dessin” (DrawArrays() ou DrawObjects()).

En mode immediat on fournit les vertices depuis le CPU à chaque vertex. Les vertex array permettent de les communiquer en une seule instructions.

Les vertex buffer object permettent de stocker les vertex sur la carte graphique et de ne plus y toucher, limitant grandement les communications entre CPU et GPU.

unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); 
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

Les zones sur la carte graphique où on stocke des informations sur des buffer objects.

Le couple glGenBuffers / glBindBuffer permet d’associer un buffer à un nombre .

glBufferData envoye les valeurs sur la carte graphique, elle ne prend pas le nombre que nous avons mais une valeur d’enumeration, ici GL_ARRAY_BUFFER.

Voici les differents canaux que nous pouvons utiliser avec glBufferData

a b a != b
0 0 0
0 1 1
1 0 1
1 1 0