OpenGL Moderne

Annexe D : Compiler vos propres applications C

De nombreux efforts ont été effectués pour que ces tutoriels soient faciles à compiler et exécuter. Malheureusement, cela signifie aussi que CMake cache la façon de faire pour votre propre projet.

Donc, ce tutoriel va expliquer comment compiler votre propre application C à partir de rien. Mais avant tout, vous avez besoin de quelques connaissances de base sur ce que votre compilateur fait.

Commentez Donner une note à l'article (5)

Article lu   fois.

Les deux auteur et traducteur

Site personnel

Traducteur : Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

Navigation

   

Sommaire

   

I. Introduction

De nombreux efforts ont été effectués pour que ces tutoriels soient faciles à compiler et exécuter. Malheureusement, cela signifie aussi que CMake cache la façon de faire pour votre propre projet.

Donc, ce tutoriel va expliquer comment compiler votre propre application C à partir de rien. Mais avant tout, vous avez besoin de quelques connaissances de base sur ce que votre compilateur fait.

Veuillez ne pas sauter les deux premières sections. Si vous lisez ce tutoriel, vous avez probablement besoin de connaître ces choses.

II. Le modèle des applications C

II-A. Le préprocesseur

On parle ici des #define et #include.

L'étape du préprocesseur est très simple : du copier-coller.

Lorsque le préprocesseur voit le code du fichier MyCode.c suivant :

 
Sélectionnez
#include "MyHeader.h"
 
void main(){
    FunctionDefinedInHeader();
}

Il ouvre simplement le fichier MyHeader.h et copie-colle son contenu dans le fichier MyCode.c.

 
Sélectionnez
// Début de MyCode.c
// Début de MyHeader.h
#ifndef MYHEADER_H
#define MYHEADER_H

void FunctionDefinedInHeader(); // Déclare la fonction

#endif
// Fin de MyHeader.h

void main(){
    FunctionDefinedInHeader(); // Utilisation
}

// Fin de MyCode.c

De façon similaire, les #define sont copiées-collées, les #if sont analysés et potentiellement retirés, etc.

À la fin de cette étape, vous obtenez un fichier C++, sans #define, #if, #ifdef, #include, prêt à être compilé.

Par exemple, voici le fichier main.cpp du sixième tutoriel, complètement prétraité dans Visual : fichier prétraité. Attention, c'est un immense fichier ! Mais cela vaut le coup de savoir ce qu'un fichier .cpp simple est réellement pour le compilateur.

II-B. Compilation

Le compilateur traduit le code C++ en une représentation que le CPU peut comprendre directement. Par exemple, le code suivant :

 
Sélectionnez
int i=3;
int j=4*i+2;

sera traduit en ces opcodes x86 :

 
Sélectionnez
mov         dword ptr [i],3
mov         eax,dword ptr [i]
lea         ecx,[eax*4+2]
mov         dword ptr [j],ecx

Chaque fichier .cpp est compilé séparément et le code binaire résultant est écrit dans des fichiers .o/.obj.

Processus de compilation

Nous n'avons pas encore l'exécutable : il reste une étape à faire.

II-C. Éditeur de liens

L'éditeur de liens prend tout le code binaire (les vôtres, mais aussi celui des bibliothèques externes) et génère l'exécutable final. Quelques notes :

  • Une bibliothèque possède l'extension .lib.
  • Certaines bibliothèques sont statiques. Cela signifie que les .lib contiennent tous les opcodes x86 nécessaires.
  • Certaines bibliothèques sont dynamiques (aussi appelées « bibliothèques partagées »). Cela signifie que le fichier .lib ne contient pas tout le code x86 ; il indique simplement : « Je jure que la fonction Foo, Bar et WhatsNot seront disponibles à l'exécution ».

Lorsque l'éditeur de liens a été exécuté, vous obtenez un exécutable (.exe sous Windows, sans extension sous Unix) :

Image non disponible

II-D. Exécution

Lorsque vous lancez l'exécutable, le système d'exploitation va ouvrir le .exe et placer les opcodes x86 en mémoire. Comme indiqué précédemment, certains codes ne sont pas disponibles à ce moment-là : le code des bibliothèques dynamiques. Mais l'éditeur de liens a été assez gentil pour indiquer où les trouver : le .exe indique clairement que la fonction glClearColor est implémentée dans le fichier OpenGL32.dll.

Exemple du produit de l'éditeur de liens

Windows va ouvrir la .dll et trouver glClearColor :

Fonctions dans Dependency Walker

Quelques fois, une .dll ne peut être trouvée, sûrement, car l'installation a échoué et le programme ne peut pas s'exécuter.

Dépendance EXE DLL

III. Comment faire X avec l'éditeur Y ?

Les instructions de compilation d'une application OpenGL sont séparées des opérations de base suivantes. En voici les raisons :

  • premièrement, vous devez faire ce genre de chose tout le temps, donc vous avez intérêt à les connaître correctement ;
  • deuxièmement, vous allez connaître ce qui est spécifique à OpenGL de ce qui ne l'est pas.

III-A. Visual Studio

III-A-1. Créer un nouveau projet

Fichier (File) → Nouveau (New) → Projet (Project) → Projet vide (Empty Project). N'utilisez pas ces étranges assistants. N'utilisez aucune option que vous ne connaissez pas (désactivez MFC, ATL, les entêtes précompilés, stdafx, le fichier main).

III-A-2. Ajouter un fichier source dans un projet

Faites un clic droit sur Fichiers sources (Sources Files) → Ajouter nouveau (Add new).

III-A-3. Ajouter un répertoire d'inclusion

Faites un clic droit sur projet (Project) → Propriétés du projet (Project Properties) → C++ → Général → Répertoire d'inclusion additionnel (Additional include directories). C'est une liste déroulante, vous pouvez la modifier comme vous le souhaitez.

III-A-4. Lier une bibliothèque

Faites un clic droit sur projet (Project) → Propriétés du projet (Project Properties) → Éditeur de liens (Linker) → Entrée (Input) → Dépendances additionnelles (Additional dependencies) : tapez le nom du fichier .lib. Par exemple : opengl32.lib.

Dans les propriétés du projet (Project Properties) → Éditeur de liens (Linker) → Général → répertoires de bibliothèques additionnels (Additional library directories), assurez-vous que le chemin de la bibliothèque ci-dessus est présent.

III-A-5. Compiler, exécuter et déboguer

Pour définir le répertoire de travail (là où sont les textures et les shaders) : Propriétés du projet (Project Properties) → Débogage (Debugging) → Répertoire de travail (Working Directory).

Pour exécuter : Maj-F5 ; mais vous ne souhaitez probablement jamais faire cela. Pour déboguer : F5.

Voici une courte liste de raccourcis pour le débogage :

  • F9 sur une ligne, ou en faisant un clic gauche sur les numéros de ligne : définit un point d'arrêt. Un point rouge va apparaître ;
  • F10 : exécuter la ligne actuelle ;
  • F11 : exécuter la ligne actuelle, mais en s'enfoncer dans les fonctions que cette ligne appelle (« Step into ») ;
  • Maj-F1 : exécuter jusqu'à la fin de la fonction (« Step out »).

Vous avez aussi de nombreuses fenêtres de débogage : les variables observées, la pile d'appels, les threads…

III-B. QtCreator

QtCreator est disponible gratuitement à cette adresse.

III-B-1. Créer un nouveau projet

Utilisez un projet vide C ou C++ ; éviter les templates contenant des trucs de Qt.

Nouveau projet dans Qt Creator

Utilisez les options par défaut.

III-B-2. Ajouter un fichier source dans un projet

Utilisez l'interface, ou ajoutez un fichier dans le .pro :

 
Sélectionnez
SOURCES += main.cpp \
           other.cpp \
           foo.cpp

III-B-3. Ajouter un répertoire d'inclusion

Dans le fichier .pro :

 
Sélectionnez
INCLUDEPATH += <chemin> \ <autre chemin>

III-B-4. Lier avec une bibliothèque

Faites un clic droit sur le projet → Ajout une bibliothèque (Add library)

  • Si vous êtes sous Linux et que vous avez installé la bibliothèque à partir de apt-get ou similaire, il y a de fortes chances que la bibliothèque soit enregistrée dans le système. Vous pouvez sélectionner « Paquet système » (System package) et entrer le nom de la bibliothèque (par exemple : libglfw ou glew).
    Image non disponible

  • Sinon, utilisez « Bibliothèque système » (System library). Naviguez jusqu'à atteindre le dossier où vous l'avez compilée.

III-B-5. Compiler, exécuter et déboguer

Pour compiler : Ctrl-B ou le marteau dans le coin inférieur gauche.

Pour exécuter : la flèche verte. Vous pouvez définir les arguments du programme et le répertoire de travail dans « Projets » (Projects) → « Paramètres d'exécution » (Run Settings).

Pour déboguer :

  • définir un point d'arrêt : cliquez à gauche des numéros de ligne. Un point rouge apparaîtra ;
  • F10 : exécuter la ligne actuelle ;
  • F11 : exécuter la ligne actuelle, mais en s'enfonçant dans les fonctions que cette ligne appelle (« Step into ») ;
  • Maj-F11 : exécuter jusqu'à la fin de la fonction (« Step out »).

Vous avez aussi de nombreuses fenêtres de débogage : les variables observées, la pile d'appels, les threads…

III-C. CMake

CMake créera les projets et cela pour pratiquement tous les outils de compilation : Visual, Qt Creator, XCode, make, Code::Blocks, Eclipse, etc., sur n'importe quel système d'exploitation. Cela vous libère de la maintenance de multiples fichiers de projet.

III-C-1. Créer un nouveau projet

Créez un fichier CMakeLists.txt et écrivez ceci (adaptez si besoin) :

 
Sélectionnez
cmake_minimum_required (VERSION 2.6)
project (le_nom_du_projet)

find_package(OpenGL REQUIRED)

add_executable(le_nom_de_l_executable
    tutorial04_colored_cube/tutorial04.cpp
    common/shader.cpp
    common/shader.hpp
)

Lancez l'interface graphique de CMake, naviguez jusqu'à atteindre votre fichier .txt et sélectionnez votre dossier de compilation. Cliquez sur « Configurer » (Configure) puis « Generer » (Generate). Votre solution va être créée dans le dossier de compilation.

III-C-2. Ajouter un fichier source dans un projet

Ajoutez simplement une ligne dans la commande add_executable.

III-C-3. Ajouter des répertoires d'inclusion

 
Sélectionnez
include_directories(
    external/AntTweakBar-1.15/include/
    external/glfw-2.7.2/include/
    external/glm-0.9.1/
    external/glew-1.5.8/include/
    .
)

III-C-4. Lier une bibliothèque

 
Sélectionnez
set(ALL_LIBS
    ${OPENGL_LIBRARY}
    GLFW_272
    GLEW_158
    ANTTWEAKBAR_151_OGLCORE_GLFW
)

target_link_libraries(tutorial01_first_window
    ${ALL_LIBS}
)

III-C-5. Compiler, exécuter et déboguer

CMake ne fait pas cela. Utilisez votre EDI favori.

III-D. Make

Veuillez, s'il vous plaît, ne pas utiliser cela.

III-E. GCC

Cela peut être intéressant de compiler un petit projet « à la main » afin de mieux comprendre le flux de travail. Ne le faites pas sur un vrai projet…

Vous pouvez aussi le faire sur Windows avec MinGW.

Compilez chaque fichier .cpp séparément :

g++ -c main.cpp
g++ -c tools.cpp

Comme indiqué précédemment, vous allez obtenir des fichiers main.o et tools.o. Liez-les :

g++ main.o tools.o

un fichier a.out apparaît ; c'est votre exécutable. Exécutez-le :

./a.out

C'est tout !

IV. Compiler votre propre application C

Armé de cette connaissance, on peut commencer à compiler soi-même une application OpenGL.

  1. Téléchargez les dépendances : ici, on utilise GLFW, GLEW et GLM, mais suivant votre projet, vous pouvez avoir besoin d'autre chose. Sauvegardez-les préférablement dans des sous-répertoires de votre projet (par exemple : external/).
  2. Elles doivent être précompilées pour votre plateforme. Toutefois, GLM n'a pas besoin d'être compilée.
  3. Créez un nouveau projet avec l'EDI de votre choix.
  4. Ajoutez un nouveau fichier .cpp dans le projet.
  5. Copiez et collez, par exemple, le code suivant (c'est en fait le fichier playground.cpp) :

     
    Sélectionnez
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <GL/glew.h>
    
    #include <GL/glfw.h>
    
    #include <glm/glm.hpp>
    using namespace glm;
    
    int main( void )
    {
        // Initialise GLFW
        if( !glfwInit() )
        {
            fprintf( stderr, "Failed to initialize GLFW\n" );
            return -1;
        }
    
        glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4);
        glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE,GL_TRUE);
        glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
        glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
        glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
        // Ouvre une fenêtre et créé son contexte OpenGL
        if( !glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW ) )
        {
            fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
            glfwTerminate();
            return -1;
        }
    
        // Initialise GLEW
        if (glewInit() != GLEW_OK) {
            fprintf(stderr, "Failed to initialize GLEW\n");
            return -1;
        }
    
        glfwSetWindowTitle( "Playground" );
    
        // Assure que l'on capture la touche Échap lorsque pressée
        glfwEnable( GLFW_STICKY_KEYS );
    
        // Fond bleu foncé
        glClearColor(0.0f, 0.0f, 0.3f, 0.0f);
    
        do{
            // Ne dessine rien, à bientôt pour le second tutoriel !
    
            // Alterne les tampons
            glfwSwapBuffers();
    
        } // Vérifie si la touche Échap a été pressée ou si la fenêtre a été fermée
        while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS &&
               glfwGetWindowParam( GLFW_OPENED ) );
    
        // Ferme la fenêtre OpenGL et termine GLFW
        glfwTerminate();
    
        return 0;
    }
  6. Compilez le projet.

Vous allez obtenir de nombreuses erreurs de compilation. On va les analyser une par une.

V. Dépannage

Les messages d'erreurs ci-dessous sont pour Visual Studio 2010, mais ils sont plus ou moins proches de ceux de GCC.

V-A. Visual Studio - fatal error C1083 : impossible d'ouvrir le fichier 'GL/glew.h' : Aucun fichier trouvé.

(Ou n'importe quel autre fichier.)

Certains entêtes ont des emplacements bizarres. Par exemple, les fichiers à inclure de GLEW sont situés dans external/glew-x.y.z/include. Le compilateur n'a aucune méthode magique pour le deviner, donc vous devez les lui indiquer. Dans les propriétés du projet, ajoutez le chemin approprié dans les options du compilateur (et non pas l'éditeur de liens).

Pour aucune raison vous ne devriez copier les fichiers dans les répertoires du compilateur (Program Files/Visual Studio/…). Techniquement, cela fonctionnera, mais c'est une très mauvaise pratique.

De plus, c'est une bonne chose d'utiliser des chemins relatifs (./external/glew/… au lieu de C:/Users/utilisateur/Downloads/…).

Par exemple, voici ce que contiennent les fichiers de CMake de ces tutoriels :

 
Sélectionnez
external/glfw-2.7.2/include
external/glm-0.9.1
external/glew-1.5.8/include

Répétez cela jusqu'à ce que tous les fichiers soient trouvés.

V-B. GCC - fatal error : GL/glew.h : aucun fichier trouvé

(ou n'importe quel autre fichier.)

Cela signifie que la bibliothèque n'est pas installée. Si vous êtes chanceux, la bibliothèque est connue et vous n'avez qu'à l'installer. C'est le cas pour GLFW, GLEW et GLM :

 
Sélectionnez
sudo apt-get install libglfw-dev libglm-dev libglew1.6-dev

Si ce n'est pas une bibliothèque répandue, regardez la réponse pour Visual Studio ci-dessus.

V-C. Visual Studio - error LNK2019 : symbole non résolu glfwGetWindowParam référencé dans la fonction main

(ou n'importe quel autre symbole dans n'importe quelle autre fonction.)

Félicitations ! Vous avez une erreur d'édition de liens. C'est une excellente nouvelle : cela signifie que la compilation a réussi. Plus qu'une dernière étape !

Les fonctions GLFW se trouvent dans une bibliothèque externe. Vous devez indiquer cette bibliothèque à l'éditeur de liens. Ajoutez-la dans les options de l'éditeur de liens. N'oubliez pas d'ajouter le chemin menant à cette bibliothèque.

Par exemple, voici ce que le projet Visual Studio utilise. Les noms sont quelque peu inhabituels, car c'est une compilation personnalisée. De plus, GLM ne nécessite pas d'être compilée ou liée, donc elle n'est pas là.

 
Sélectionnez
external\Debug\GLFW_272.lib
external\Debug\GLEW_158.lib

Si vous téléchargez ces bibliothèques à partir de SourceForge (GLFW, GLEW) et les compilez vous-même, vous devez spécifier le chemin adéquat. Par exemple :

 
Sélectionnez
C:\Ou\Vous\Avez\Place\La\Bibliotheque\glfw.lib
C:\Ou\Vous\Avez\Place\La\Bibliotheque\glew32.lib

V-D. GCC - main.cpp : référence indéfinie vers 'glfwInit'

(ou n'importe quel autre symbole.)

Même réponse que pour Visual Studio ci-dessus.

Sur Linux, GLFW et GLEW (et plein d'autres) sont généralement installées avec apt-get ou autre : sudo apt-get install libglew-dev libglfw-dev (cela peut changer). Lorsque vous faites ceci, les bibliothèques sont copiées dans les répertoires standards du compilateur, donc vous n'avez pas à préciser le chemin. Liez simplement glfw et glew comme présenté dans la première section.

V-E. J'ai tout configuré correctement, mais j'ai toujours une erreur « unresolved external error » !

Cela peut être quelque peu difficile à tracer. Il y a plusieurs solutions :

V-E-1. J'ai une erreur durant l'édition des liens avec _imp_glewInit ou d'autres symboles qui commencent par _imp

Cela signifie que la bibliothèque (dans ce cas, glew) a été compilée comme bibliothèque statique, mais vous essayez de l'utiliser comme bibliothèque dynamique. Ajoutez simplement la définition pour le préprocesseur suivante dans les options du compilateur (pour votre propre projet, et non celui de glew) :

 
Sélectionnez
GLEW_STATIC

V-E-2. J'ai quelques problèmes étranges avec GLFW

Peut-être, car GLFW a été compilée comme bibliothèque dynamique, mais vous essayez de l'utiliser comme bibliothèque statique ?

Essayez d'ajouter la définition pour le préprocesseur suivante :

 
Sélectionnez
GLFW_DLL

V-E-3. J'ai un autre problème avec l'éditeur de liens ! Aidez-moi, je suis bloqué !

Veuillez envoyer un rapport détaillé et un projet complet compressé et on ajoutera des indications.

V-E-4. J'aimerais résoudre cela moi-même. Quelles sont les règles générales ?

Admettons que vous êtes l'auteur de la GLFW. Vous souhaitez fournir la fonction glfwInit().

Lors de la compilation comme DLL, vous devez indiquer au compilateur que glfwInit() n'est pas comme n'importe quelle autre fonction dans la DLL ; elle doit être vue par les autres, contrairement à glfwPrivateImplementationMethodNobodyShouldCareAbout(). Cela est fait en déclarant la fonction externe « external » avec GCC, ou « __declspec(dllexport) » avec Visual.

Lorsque vous souhaitez utiliser GLFW, vous devez indiquer au compilateur que la fonction n'est pas réellement disponible : il doit la lier dynamiquement. Cela est fait en déclarant la fonction externe « external » avec GCC ou « __declspec(dllimport) » avec Visual.

Donc vous utilisez une définition pratique #define : GLFWAPI et vous l'utilisez pour déclarer les fonctions :

GLFWAPI int glfwInit(void) ;

  • lorsque vous compilez la bibliothèque en DLL, vous définissez #define GLFW_BUILD_DLL. GLFWAPI sera alors défini en __declspec(dllexport) ;
  • lorsque vous utilisez GLFW à travers une DLL, vous définissez #define GLFW_DLL. GLFWAPI sera alors défini en __declspec(dllimport) ;
  • lorsque vous compilez la bibliothèque statique, GLFWAPI est défini vide.
  • Lorsque vous utilisez GLFW en bibliothèque statique, GLFWAPI est défini vide.

Donc la règle est : ces indications doivent être consistantes. Si vous compilez une bibliothèque (n'importe quelle bibliothèque, pas que GLFW) en DLL, utilisez la bonne définition pour le préprocesseur : GLFW_DLL, GLEW_STATIC.

V-F. Mon programme crashe !

Il y a de multiples raisons qu'une application C++ OpenGL plante. Voici quelques-unes d'entre elles. Si vous ne connaissez pas la ligne exacte où votre programme plante, apprenez à utiliser un débogueur (voir les raccourcis ci-dessus). Veuillez NE PAS déboguer avec printf().

V-F-1. Je n'atteins même pas le main

Cela est certainement dû à des DLL qui n'ont pas pu être trouvées. Essayez d'ouvrir votre application avec Dependency Walker (Windows) ou ldd (Linux ; essayez aussi ceci).

V-F-2. Mon programme crashe sur glfwOpenWindow(), ou toute autre fonction qui crée un contexte OpenGL

Plusieurs raisons existent :

  • votre GPU ne supporte pas la version OpenGL demandée. Essayez de voir la version supportée avec GPU Caps Viewer ou un outil similaire. Mettez à jour vos pilotes si la version semble trop faible. Les cartes intégrées Intel sur les netbooks sont particulièrement nulles. Utilisez une version d'OpenGL plus basse (2.1 par exemple) et utilisez les extensions si vous manquez de fonctionnalités ;
  • votre système d'exploitation ne supporte pas la version OpenGL demandée : Mac OS… même réponse ;
  • vous essayez d'utiliser GLEW avec un contexte OpenGL core (c'est-à-dire, sans les choses dépréciées). C'est un bogue de GLEW. Utilisez glewExperimental=true avec glewInit() ou utilisez le mode de compatibilité (c'est-à-dire utilisez GLFW_OPENGL_COMPAT_PROFILE à la place de GLFW_OPENGL_CORE_PROFILE).

V-G. Mon programme crashe sur le premier appel OpenGL, ou sur la première création de tampon

Trois raisons sont possibles :

  • vous n'avez pas appelé glewInit() APRÈS glfwOpenWindow() ;
  • vous utilisez un profil OpenGL core et vous n'avez pas créé de VAO. Ajoutez le code suivant après glewInit() :

     
    Sélectionnez
    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);
  • Vous utilisez la version de GLEW par défaut, qui contient un bogue. Vous ne pouvez utiliser un profil OpenGL core à cause de celui-ci. Utilisez soit glewExperimental=true

  • avec glewInit(), ou demandez à GLFW d'utiliser un profil de compatibilité à la place :
 
Sélectionnez
glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);

V-H. Mon programme crashe lorsque j'essaie de charger un fichier

Définissez votre répertoire de travail correctement. Lisez le premier tutoriel.

Créez un fichier test.txt et essayez le code suivant :

 
Sélectionnez
if ( fopen("test.txt", "r" ) == NULL ){
    printf("I'm probably running my program from a wrong folder");
}

UTILISEZ LE DÉBOGUEUR !

Sincèrement ! Ne déboguez pas avec printf() ; utilisez un bon EDI. http://www.dotnetperls.com/debugging est pour le C# mais est aussi valide pour le C++. Cela peut être différent pour XCode ou Qt Creator, mais les concepts restent exactement les mêmes.

V-I. Autre chose ne va pas

Veuillez utiliser le forum.

VI. Remerciements

Cet article est une traduction autorisée dont le texte original peut être trouvé sur opengl-tutorial.org.

Navigation

   

Sommaire

   

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2014 opengl-tutorial.org. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.