Pour comprendre ce tutoriel il est nécessaire d'avoir quelques bases de connaissances en langage C.
Ce guide se base sur le tutoriel disponible à cette adresse:
Wikibooks - OpenGL Programming/Modern OpenGL Introduction
J'ai converti le code source de ce tutoriel afin qu'il soit pleinement compatible en langage C.
Aussi je vais tenter d'expliquer en quoi consiste chacune des
fonctions qui seront déclarées dans ce tutoriel.
Et à la
différence du guide disponible sur le wikibooks, nous allons
utiliser la bibliothèque Glad plutôt que Glew.
OpenGL est une API graphique pour le traitement d'image 2D et 3D lancé par Silicon Graphics en 1992. Cette interface de programmation est multiplateforme et écrite en C.
OpenGL permet à un programme de déclarer la géométrie d'objets sous forme de points, de vecteurs, de polygones et de textures. OpenGL effectue ensuite des calculs de projection en vue de déterminer l'image à l'écran, en tenant compte de la distance, de l'orientation, des ombres, de la transparence et du cadrage.
Source: Wikipedia - OpenGL
Simple DirectMedia Layer est une bibliothèque de développement multiplateforme conçue pour fournir un accès de bas niveau au matériel audio, clavier, souris, joystick et graphique via OpenGL/Direct3D/Metal/Vulkan.
Source: Wiki - SDL
En somme c'est une bibliothèque multimédia permettant entre autre de concevoir des jeux-vidéos ou applications graphique comme nous allons le faire dans ce tutoriel. Cette bibliothèque nous permettra de créer un contexte OpenGL dans une fenêtre gérée par la bibliothèque SDL.
GLAD simplifie le processus de gestion des pointeurs de fonctions d'OpenGL. Il génère du code spécifique à la plate-forme pour les fonctions OpenGL, ceci simplifie l'utilisation d'OpenGL et de manière multiplateforme.
Donc, il vous faudra pour ce tutoriel:
Créez un répertoire pour ce projet dans lequel
vous créez aussi le nouveau fichier main.c.
Téléchargez glad.zip
pour OpenGL 2.1 et extrayez-la dans le dossier que vous venez
de créer.
Deux dossiers apparaissent à côté de main.c:
Je vais faire un code minimaliste pour commencer ce tutoriel.
Éditez avec votre bloc note ou votre IDE le fichier main.c et inscrivez-y ce qui suit.
//Directives préprocesseur: chargement des bibliothèques SDL2 et Glad
#include <SDL2/SDL.h>
#include "glad/glad.h"
//Fonction principale, point d'entrée du programme
int main(int argc, char* argv[]){
//Fonction d'initialisation de la SDL (seulement la vidéo dans ce tutoriel)
SDL_Init(SDL_INIT_VIDEO);
//Fin réussie du programme, retourne 0
return EXIT_SUCCESS;
}
Je vous encourage à le tester si la compilation fonctionne chez vous.
Pour la compilation il faut au préalable avoir installé la librairie SDL2, ainsi
que la bibliothèque Glad via la procédure expliquée ci-dessus
concernant Glad.
Un dernier détail, il vous faudra "linker" ces bibliothèques vis-a-vis du compilateur GCC. Les paramètres -lSDL2 et -ldl.
Voici la ligne de commande à utiliser pour la compilation du projet dans son dossier:
gcc -I ./include glad.c main.c -o main -lSDL2 -ldl
Après cette première compilation, revenons-en au code. Nous allons créer la fenêtre SDL2 ainsi que le contexte OpenGL dans cette partie.
Tapez le code qui suit sous la ligne:
SDL_Init(SDL_INIT_VIDEO);
//Crée la fenêtre SDL (titre, position, taille, utilisable avec un contexte OpenGL)
SDL_Window* win =SDL_CreateWindow("Triangle SDL2 + OpenGL",
SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,
640,480,
SDL_WINDOW_OPENGL|SDL_WINDOW_OPENGL);
//Crée le contexte OpenGL => gContext
SDL_GLContext gContext=SDL_GL_CreateContext(win);
À ce stade si vous compilez ce code et que vous exécutez l'application vous pourrez apercevoir une fenêtre s'ouvrir et se fermer aussitôt, car il n'y a aucune pause dans ce code donc le programme quitte instantanément.
Continuons! Nous allons implémenter une fonction pour libérer les ressources
utilisées par le programme, juste avant de quitter l'application.
Cette fonction sera appelée freeRessource.
//Fonction qui libère les ressources
void freeRessources(SDL_Window*win,SDL_GLContext gContext){
//Supprime le contexte OpenGL
SDL_GL_DeleteContext(gContext);
//Détruit la fenêtre
SDL_DestroyWindow(win);
//Quitte la SDL2
SDL_Quit();
}
Cette fonction prend en paramètre la fenêtre SDL_Window ainsi que le contexte OpenGL pour le moment, car c'est tous ce qu'on a créé comme ressources.
Placez la ligne suivant dans la fonction principale main du programme juste avant les lignes:
//Fin réussie du programme, retourne 0 return EXIT_SUCCESS;
//Libère les ressources du programme.
freeRessources(win,gContext);
Cette ligne fait appel à la fonction qui libèrera les ressource juste avant de terminer le programme.
Pour définir la configuration souhaitée d'OpenGL dans notre application, il est nécessaire de passer quelques lignes de codes.
Vous pouvez les placer juste à la suite de l'initialisation de la SDL (vidéo) sous la ligne:
SDL_Init(SDL_INIT_VIDEO);
//Définition des attributs du contexte OpenGL
//Active le double buffering
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//Version d'OpenGL que nous souhaitons utiliser => 2.1
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
//Cette fonction force l'utilisation des fonctions dites CORE d'OpenGL 2.1
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
Il nous faudra charger Glad afin d'utiliser OpenGL. Pour ce faire nous devons faire appel à la fonction gladLoadGLLoader(). Inscrivez les lignes qui suivent dans votre code juste après la création de contexte OpenGL, donc à la suite de la ligne ci-dessous:
SDL_GLContext gContext=SDL_GL_CreateContext(win);
//Chargement de Glad
int version = gladLoadGLLoader((GLADloadproc) SDL_GL_GetProcAddress);
if(!version){
printf("Glad was not initialized.\n");
exit(1);
}
else{
printf("OpenGL Renderer: %s\n",glGetString(GL_VENDOR));
printf("OpenGL Renderer: %s\n",glGetString(GL_VERSION));
}
Normalement si vous compilez et lancé le programme à ce stade votre invite de commande devrait afficher des informations concernant votre carte graphique (vendeur) ainsi que la version d'OpenGL utilisée.
Afin que l'application puisse continuer presque indéfiniment de tourner, il nous faut créer une boucle dans notre programme.
Pour ce faire nous allons créer une fonction qui contiendra la boucle principale de l'application et qui sera appelée dans la fonction main() de notre programme.
Placez cette ligne de code dans le fichier main.c juste avant l'appel de fonction qui libère les ressource; c.a.d:
//Libère les ressources du programme. freeRessources(win,gContext,program);
//Boucle principale du programme.
mainLoop();
A l'extérieur, au dessus de la fonction main(), créez la fonction mainLoop() en inscrivant ces lignes:
void mainLoop(){
//Boolean qui permet de quitter la boucle
SDL_bool quit=SDL_FALSE;
//Boucle principale (Boucle si la variable quit = faux)
while(!quit){
}
}
Attention:
A ce stade, après compilation du code, vous devriez avoir une
application qui tourne en boucle sans moyen d'autre de sortie que
de forcer l'arrêt de l'application via par exemple votre gestionnaire
de tâche (Ctrl+Alt+Delete sous Windows).
Aussi vous noterez, que l'application n'a pas une couleur définie en fond. C'est parce que nous n'avons pas encore fait appel à une fonction de rendu, donc rien ne s'affiche correctement si ce n'est que le contour de la fenêtre pour le moment. Nous verrons la fonction de rendu dans prochainement sur cette page, en attendant nous allons tenter de quitter ce programme correctement via un événement (interactivité entre l'utilisateur et la machine).
Pour quitter le programme il faudra gérer un événement dans notre boucle principale. Celui-ci se chargera de capter un événement de fermeture d'application via la librairie SDL.
Pour ce faire nous allons transformer la fonction mainLoop() en y inscrivant le code qui suit à la place:
void mainLoop(){
//Boolean qui permet de quitter la boucle
SDL_bool quit=SDL_FALSE;
//Evênement SDL (e)
SDL_Event e;
//Boucle principale (Boucle si la variable quit = faux)
while(!quit){
//Test si un événement à lieu
if(SDL_PollEvent(&e)!=0){
/*Si c'est un événement de type SDL_QUIT Fermeture de la fenêtre
la variable "quit" aura la valeur true.=> 1 et on sortira de la boucle.*/
if(e.type==SDL_QUIT)
quit=SDL_TRUE;
//Teste si une touche est pressée.
else if(e.type==SDL_KEYDOWN){
//Si on appuie sur la touche ESCAPE => On quitte la boucle (quit=true).
if(e.key.keysym.sym==SDLK_ESCAPE)
quit=SDL_TRUE;
}
}
}
}
Voilà, maintenant nous pouvons compiler le programme, le tester et le quitter proprement. Il nous reste plus que de nous occuper du rendu dans le contexte OpenGL.
Nous allons faire un rendu minimaliste, c'est à dire un unique fond de couleur noir dans le contexte OpenGL.
La procédure que nous allons utiliser est de créer une fonction de rendu qui sera appelée dans la boucle principale précédemment créée.
Pourquoi placer la fonction de rendu dans la boucle principale?
Pour rafraichir l'affichage du contexte OpenGL et éviter ainsi que
notre fenêtre donne des signe de "bugs" d'affichage en restant
bien d'une couleur unie.
À présent, créez la nouvelle fonction juste après les deux lignes #include ... tout en haut du fichier main.c et nommez cette nouvelle fonction render() en tapant ceci:
//Fonction de rendu
void render(SDL_Window* win){
// Choisi une couleur de fond (au format rouge, vert, bleu et alpha)
glClearColor(0.0, 0.0, 0.0, 1.0);
// Applique la couleur de fond
glClear(GL_COLOR_BUFFER_BIT);
/* Met à jour le résultat*/
SDL_GL_SwapWindow(win);
}
Aussi, faite appel à cette nouvelle fonction dans la boucle principale du programme après la section de test d'évènements:
if(SDL_PollEvent(&e)!=0){...}
//Appel la fonction de rendu
render(win);
Constatez que l'on passe la fenêtre en paramètre de fonction 'win'.
Donc, nous devons récupérer également la fenêtre SDL_Window dans la fonction mainLoop
Pour ce faire changez la première ligne du prototype de fonction de mainLoop avec ceci:
void mainLoop(SDL_Window *win){
Et dans la fonction main on change l'appel de fonction mainLoop(); en ceci pour passer la fenêtre SDL_Window créée au tout début de ce tutoriel:
mainLoop(win);
On est bon pour la compilation et observer le résultat! Une magnifique fenêtre OpenGL avec fond noir.
le code source complet de ce tutoriel est disponible ici