Skip to content

Latest commit

 

History

History
853 lines (644 loc) · 21.4 KB

File metadata and controls

853 lines (644 loc) · 21.4 KB

🔝 Retour au Sommaire

12.3 OpenGL multi-plateforme

Introduction

OpenGL (Open Graphics Library) est une API standard de l'industrie pour le rendu 2D et 3D accéléré par GPU. Créée en 1992, elle reste aujourd'hui l'une des technologies graphiques les plus utilisées au monde, particulièrement dans les domaines de la visualisation scientifique, des jeux vidéo, de la CAO/DAO et des applications graphiques professionnelles.

Cette section vous guidera dans l'utilisation d'OpenGL avec FreePascal et Lazarus, en mettant l'accent sur la portabilité entre Windows et Ubuntu/Linux tout en garantissant des performances maximales.


Pourquoi utiliser OpenGL ?

Avantages d'OpenGL

1. Accélération matérielle (GPU)

  • Exploite la puissance de calcul parallèle des cartes graphiques
  • Performances 10 à 100 fois supérieures au rendu CPU pour le graphisme 3D
  • Libère le CPU pour d'autres tâches

2. Multi-plateforme par nature

  • Fonctionne sur Windows, Linux, macOS, BSD
  • API identique sur toutes les plateformes
  • Code source portable sans modification

3. Standard industriel

  • Supporté par tous les fabricants de GPU (NVIDIA, AMD, Intel)
  • Documentation abondante et communauté active
  • Pilotes matures et optimisés

4. Flexibilité et puissance

  • Rendu 2D et 3D
  • Shaders programmables (GLSL)
  • Effets visuels avancés (ombres, reflets, post-processing)
  • Support des textures, lighting, animations

5. Performance prédictible

  • Pipeline de rendu bien défini
  • Outils de profiling disponibles
  • Optimisations connues et documentées

Comparaison : Canvas/BGRABitmap vs OpenGL

Aspect Canvas/BGRABitmap OpenGL
Type de rendu CPU (logiciel) GPU (matériel)
Performance 2D simple Excellente Bonne
Performance 2D complexe Moyenne Excellente
Performance 3D Très faible Excellente
Nombre d'objets Milliers Millions
Courbe d'apprentissage Facile Moyenne
Portabilité Parfaite Excellente
Complexité du code Simple Moyenne à complexe

Quand utiliser OpenGL ?

Utilisez OpenGL pour :

  • Applications 3D (modélisation, visualisation, jeux)
  • Rendu de milliers d'objets simultanément
  • Animations complexes temps réel (60+ FPS)
  • Visualisation scientifique de données volumineuses
  • Effets visuels avancés (particules, shaders, post-processing)
  • Applications nécessitant une fluidité maximale

N'utilisez PAS OpenGL pour :

  • Interfaces simples (boutons, formulaires standards)
  • Applications business classiques
  • Graphiques statiques ou peu dynamiques
  • Projets où la simplicité prime sur la performance

Architecture OpenGL avec Lazarus

Vue d'ensemble de l'intégration

┌─────────────────────────────────────────┐
│   Application Lazarus                   │
│   - Votre code FreePascal               │
├─────────────────────────────────────────┤
│   TOpenGLControl (Lazarus)              │
│   - Composant LCL                       │
│   - Gestion du contexte OpenGL          │
├─────────────────────────────────────────┤
│   Bibliothèques OpenGL Pascal           │
│   - gl.pas, glu.pas, glext.pas          │
│   - Wrapper des fonctions OpenGL        │
├─────────────────────────────────────────┤
│   Bibliothèque OpenGL système           │
│   Windows: opengl32.dll                 │
│   Linux: libGL.so                       │
├─────────────────────────────────────────┤
│   Pilote GPU                            │
│   - NVIDIA, AMD, Intel                  │
│   - Traduction vers instructions GPU    │
├─────────────────────────────────────────┤
│   GPU (Carte graphique)                 │
│   - Exécution du rendu                  │
└─────────────────────────────────────────┘

Composant TOpenGLControl

Lazarus fournit le composant TOpenGLControl qui :

  • Crée et gère le contexte OpenGL
  • S'intègre naturellement dans l'IDE Lazarus
  • Gère les événements de rendu (OnPaint)
  • Fonctionne identiquement sur Windows et Linux
  • Support du double buffering automatique
uses
  OpenGLContext, GL, GLU;

type
  TForm1 = class(TForm)
    OpenGLControl1: TOpenGLControl;
    procedure OpenGLControl1Paint(Sender: TObject);
  end;

procedure TForm1.OpenGLControl1Paint(Sender: TObject);  
begin
  // Effacer l'écran
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  // Votre code de rendu OpenGL ici

  // Échanger les buffers (afficher)
  OpenGLControl1.SwapBuffers;
end;

Concepts fondamentaux d'OpenGL

Le pipeline de rendu

OpenGL fonctionne selon un pipeline (chaîne de traitement) :

1. Vertices (sommets)
   ↓
2. Vertex Shader (transformation)
   ↓
3. Primitive Assembly (assemblage)
   ↓
4. Rasterization (conversion en pixels)
   ↓
5. Fragment Shader (coloration)
   ↓
6. Tests et mélange
   ↓
7. Framebuffer (affichage)

Système de coordonnées

OpenGL utilise un système de coordonnées 3D :

        Y
        │
        │
        │
        └────────── X
       ╱
      ╱
     Z
  • X : Gauche (-) à Droite (+)
  • Y : Bas (-) à Haut (+)
  • Z : Arrière (-) à Avant (+)

Par défaut, le système est normalisé de -1 à +1 sur chaque axe.

Primitives de base

OpenGL dessine à partir de primitives géométriques :

Primitive Description Exemple d'usage
GL_POINTS Points individuels Particules, étoiles
GL_LINES Lignes Wireframe, grilles
GL_LINE_STRIP Ligne continue Courbes, graphiques
GL_TRIANGLES Triangles Surfaces, modèles 3D
GL_TRIANGLE_STRIP Bande de triangles Terrains, surfaces
GL_QUADS Quadrilatères Sprites 2D
// Dessiner un triangle
glBegin(GL_TRIANGLES);
  glVertex3f(0.0, 1.0, 0.0);   // Sommet haut
  glVertex3f(-1.0, -1.0, 0.0); // Sommet bas gauche
  glVertex3f(1.0, -1.0, 0.0);  // Sommet bas droit
glEnd;

États et contexte

OpenGL est une machine à états :

  • Vous configurez des états (couleur, textures, etc.)
  • Les états restent actifs jusqu'à modification
  • Le contexte conserve tous les états
// Définir la couleur de dessin
glColor3f(1.0, 0.0, 0.0);  // Rouge

// Tous les dessins suivants seront rouges
glBegin(GL_TRIANGLES);
  // Triangle rouge
glEnd;

// Changer de couleur
glColor3f(0.0, 0.0, 1.0);  // Bleu

glBegin(GL_QUADS);
  // Carré bleu
glEnd;

Versions d'OpenGL

Évolution historique

Version Année Caractéristiques principales
OpenGL 1.x 1992-2003 Pipeline fixe, fonctions immédiates
OpenGL 2.x 2004-2006 Introduction des shaders (GLSL)
OpenGL 3.x 2008-2010 Dépréciation du pipeline fixe
OpenGL 4.x 2010-2017 Compute shaders, tesselation
OpenGL 4.6 2017 Version actuelle, optimisations

Profils OpenGL

Legacy (Compatibilité)

  • Supporte les anciennes fonctions (glBegin/glEnd)
  • Plus simple pour débuter
  • Performances moins optimales
  • Recommandé pour l'apprentissage

Core (Moderne)

  • Pipeline moderne uniquement
  • Shaders obligatoires
  • Meilleures performances
  • Plus complexe
  • Recommandé pour la production

Choix pour ce tutoriel

Nous utiliserons principalement OpenGL 2.1 avec shaders car il offre :

  • ✅ Compatibilité maximale (Windows XP+, Linux ancien)
  • ✅ Supporte les shaders (moderne)
  • ✅ API simple pour débuter
  • ✅ Performance excellente
  • ✅ Support universel (tous les GPU depuis 2006)

OpenGL et FreePascal/Lazarus

Packages nécessaires

Pour utiliser OpenGL avec Lazarus, vous aurez besoin de :

  1. OpenGLContext (inclus dans Lazarus)

    • Package : lazopenglcontext.lpk
    • Fournit TOpenGLControl
  2. Unités OpenGL (incluses dans FreePascal)

    • GL : Fonctions OpenGL de base
    • GLU : Utilitaires OpenGL
    • GLext : Extensions OpenGL

Installation du support OpenGL

Sur Windows

  • OpenGL est inclus dans Windows (opengl32.dll)
  • Aucune installation supplémentaire nécessaire
  • Les pilotes GPU incluent l'implémentation

Sur Ubuntu/Linux

# Installer les bibliothèques de développement OpenGL
sudo apt-get update  
sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev

# Vérifier l'installation
glxinfo | grep "OpenGL version"

Installation du package dans Lazarus

  1. Menu PaquetOuvrir un fichier paquet (.lpk)
  2. Naviguer vers : lazarus/components/opengl/lazopenglcontext.lpk
  3. Cliquer sur Compiler
  4. Cliquer sur UtiliserAjouter aux composants du projet

Le composant TOpenGLControl apparaît alors dans la palette System.


Exemple minimal

Voici un programme minimal OpenGL avec Lazarus :

unit MainForm;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
  OpenGLContext, GL, GLU;

type
  TForm1 = class(TForm)
    OpenGLControl1: TOpenGLControl;
    procedure FormCreate(Sender: TObject);
    procedure OpenGLControl1Paint(Sender: TObject);
  private
    procedure InitOpenGL;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

procedure TForm1.FormCreate(Sender: TObject);  
begin
  InitOpenGL;
end;

procedure TForm1.InitOpenGL;  
begin
  // Configuration initiale OpenGL
  glClearColor(0.2, 0.3, 0.4, 1.0);  // Couleur de fond (bleu foncé)
  glEnable(GL_DEPTH_TEST);            // Activer le test de profondeur
end;

procedure TForm1.OpenGLControl1Paint(Sender: TObject);  
begin
  // Effacer l'écran
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  // Réinitialiser la matrice de vue
  glLoadIdentity;

  // Dessiner un triangle simple
  glBegin(GL_TRIANGLES);
    glColor3f(1.0, 0.0, 0.0);  // Rouge
    glVertex3f(0.0, 1.0, -5.0);

    glColor3f(0.0, 1.0, 0.0);  // Vert
    glVertex3f(-1.0, -1.0, -5.0);

    glColor3f(0.0, 0.0, 1.0);  // Bleu
    glVertex3f(1.0, -1.0, -5.0);
  glEnd;

  // Afficher (swap buffers)
  OpenGLControl1.SwapBuffers;
end;

end.

Fichier .lfm associé

object Form1: TForm1
  Left = 300
  Height = 600
  Top = 200
  Width = 800
  Caption = 'OpenGL avec Lazarus'
  OnCreate = FormCreate

  object OpenGLControl1: TOpenGLControl
    Left = 0
    Height = 600
    Top = 0
    Width = 800
    Align = alClient
    OnPaint = OpenGLControl1Paint
  end
end

Ce code affiche : Un triangle coloré avec dégradé RGB sur fond bleu foncé.


Concepts clés à comprendre

1. Le contexte OpenGL

Le contexte est l'environnement OpenGL complet :

  • Créé automatiquement par TOpenGLControl
  • Un par composant OpenGL
  • Contient tous les états OpenGL
  • Doit être actif pour les appels OpenGL
// S'assurer que le contexte est actif
OpenGLControl1.MakeCurrent;

// Appels OpenGL possibles maintenant
glClear(GL_COLOR_BUFFER_BIT);

2. Double buffering

Pour éviter les scintillements, OpenGL utilise deux buffers :

  • Back buffer : On dessine dedans (invisible)
  • Front buffer : Affiché à l'écran
// Dessiner dans le back buffer
glClear(...);
// ... dessins ...

// Échanger back ↔ front (afficher)
OpenGLControl1.SwapBuffers;

3. La boucle de rendu

Dans une application OpenGL typique :

procedure TForm1.IdleLoop(Sender: TObject; var Done: Boolean);  
begin
  // Mettre à jour la logique
  UpdateScene(DeltaTime);

  // Redessiner
  OpenGLControl1.Invalidate;  // Déclenche OnPaint

  Done := False;  // Continue la boucle
end;

procedure TForm1.FormCreate(Sender: TObject);  
begin
  Application.OnIdle := @IdleLoop;
end;

4. Viewport et projection

Le viewport définit la zone de dessin :

procedure TForm1.OpenGLControl1Resize(Sender: TObject);  
var
  W, H: Integer;
begin
  W := OpenGLControl1.Width;
  H := OpenGLControl1.Height;

  if H = 0 then H := 1;  // Éviter division par zéro

  // Définir le viewport
  glViewport(0, 0, W, H);

  // Configuration de la projection
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(45.0, W / H, 0.1, 100.0);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
end;

Matrices et transformations

Les trois matrices principales

OpenGL utilise trois matrices pour transformer les objets :

1. Modelview Matrix (GL_MODELVIEW)

  • Position et orientation des objets
  • Vue de la caméra
glMatrixMode(GL_MODELVIEW);  
glLoadIdentity;  
glTranslatef(2.0, 0.0, -5.0);  // Déplacer  
glRotatef(45.0, 0.0, 1.0, 0.0); // Rotation 45° autour Y  
glScalef(2.0, 2.0, 2.0);        // Agrandir 2×

2. Projection Matrix (GL_PROJECTION)

  • Définit comment la 3D est projetée en 2D
  • Perspective ou orthographique
glMatrixMode(GL_PROJECTION);  
glLoadIdentity;

// Projection perspective (3D réaliste)
gluPerspective(
  45.0,              // FOV (Field of View) en degrés
  Width / Height,    // Ratio d'aspect
  0.1,               // Near clipping plane
  100.0              // Far clipping plane
);

// OU projection orthographique (2D, CAO)
glOrtho(-10, 10, -10, 10, -10, 10);

3. Texture Matrix (GL_TEXTURE)

  • Rarement utilisée
  • Transformations des coordonnées de texture

Pile de matrices

OpenGL maintient une pile de matrices :

// Sauvegarder l'état actuel
glPushMatrix;

  // Transformations temporaires
  glTranslatef(1.0, 0.0, 0.0);
  // Dessiner quelque chose

// Restaurer l'état précédent
glPopMatrix;

Gestion des couleurs et matériaux

Couleurs directes

// RGB (0.0 à 1.0)
glColor3f(1.0, 0.0, 0.0);  // Rouge

// RGBA (avec transparence)
glColor4f(1.0, 0.0, 0.0, 0.5);  // Rouge semi-transparent

// Par vertex (dégradé automatique)
glBegin(GL_TRIANGLES);
  glColor3f(1.0, 0.0, 0.0); glVertex3f(0.0, 1.0, 0.0);
  glColor3f(0.0, 1.0, 0.0); glVertex3f(-1.0, -1.0, 0.0);
  glColor3f(0.0, 0.0, 1.0); glVertex3f(1.0, -1.0, 0.0);
glEnd;

Matériaux et éclairage

// Activer l'éclairage
glEnable(GL_LIGHTING);  
glEnable(GL_LIGHT0);

// Définir une source de lumière
var
  LightPos: array[0..3] of GLfloat = (5.0, 5.0, 5.0, 1.0);
  LightColor: array[0..3] of GLfloat = (1.0, 1.0, 1.0, 1.0);
begin
  glLightfv(GL_LIGHT0, GL_POSITION, @LightPos);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, @LightColor);
end;

// Définir un matériau
var
  MatAmbient: array[0..3] of GLfloat = (0.2, 0.2, 0.2, 1.0);
  MatDiffuse: array[0..3] of GLfloat = (0.8, 0.0, 0.0, 1.0);
  MatSpecular: array[0..3] of GLfloat = (1.0, 1.0, 1.0, 1.0);
begin
  glMaterialfv(GL_FRONT, GL_AMBIENT, @MatAmbient);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, @MatDiffuse);
  glMaterialfv(GL_FRONT, GL_SPECULAR, @MatSpecular);
  glMaterialf(GL_FRONT, GL_SHININESS, 32.0);
end;

Performance et optimisation

Techniques d'optimisation principales

1. Réduction des appels OpenGL

// ❌ MAUVAIS : Beaucoup d'appels
for i := 0 to 1000 do  
begin
  glBegin(GL_TRIANGLES);
    // Un seul triangle
  glEnd;
end;

// ✅ BON : Un seul appel
glBegin(GL_TRIANGLES);
  for i := 0 to 1000 do
  begin
    // 1000 triangles
  end;
glEnd;

2. Utilisation de VBO (Vertex Buffer Objects)

// Créer un buffer GPU
var
  VBO: GLuint;
begin
  glGenBuffers(1, @VBO);
  glBindBuffer(GL_ARRAY_BUFFER, VBO);
  glBufferData(GL_ARRAY_BUFFER, SizeOf(Vertices), @Vertices, GL_STATIC_DRAW);
end;

3. Culling (élimination des faces cachées)

glEnable(GL_CULL_FACE);  
glCullFace(GL_BACK);  // Ne pas dessiner les faces arrière

4. Level of Detail (LOD)

  • Utiliser des modèles simplifiés pour les objets lointains
  • Réduire le nombre de polygones selon la distance

Mesure de performance

// FPS (Frames Per Second)
var
  FrameCount: Integer;
  LastTime, CurrentTime: TDateTime;
  FPS: Double;
begin
  Inc(FrameCount);
  CurrentTime := Now;

  if MilliSecondsBetween(CurrentTime, LastTime) >= 1000 then
  begin
    FPS := FrameCount;
    FrameCount := 0;
    LastTime := CurrentTime;

    Caption := Format('FPS: %.1f', [FPS]);
  end;
end;

Portabilité Windows/Linux

Code portable

Le code OpenGL est naturellement portable :

// Ce code fonctionne identiquement sur Windows et Linux
procedure RenderScene;  
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;

  glTranslatef(0.0, 0.0, -5.0);
  glRotatef(Angle, 0.0, 1.0, 0.0);

  DrawCube;

  OpenGLControl1.SwapBuffers;
end;

Différences à gérer

Chemins de fichiers

{$IFDEF WINDOWS}
  TexturePath := 'C:\Textures\';
{$ENDIF}
{$IFDEF LINUX}
  TexturePath := '/home/user/textures/';
{$ENDIF}

// Meilleure approche : chemins relatifs
TexturePath := 'textures' + PathDelim;

Extensions OpenGL

// Charger les extensions (même code partout)
uses
  GLext;

// Vérifier la disponibilité
if Load_GL_version_2_0 then
  WriteLn('OpenGL 2.0 disponible');

Vérification du support

procedure CheckOpenGLVersion;  
var
  Version, Vendor, Renderer: PChar;
begin
  Version := glGetString(GL_VERSION);
  Vendor := glGetString(GL_VENDOR);
  Renderer := glGetString(GL_RENDERER);

  WriteLn('OpenGL Version: ', Version);
  WriteLn('Vendor: ', Vendor);
  WriteLn('Renderer: ', Renderer);
end;

Ressources et outils

Documentation officielle

Tutoriels recommandés

Outils de développement

  • RenderDoc : Debugger OpenGL graphique
  • GLIntercept : Trace des appels OpenGL
  • gDEBugger : Profiler OpenGL

Structure des sections suivantes

Ce chapitre 12.3 est organisé comme suit :

12.3.1 Configuration OpenGL Windows

  • Installation et configuration
  • Contexte OpenGL sous Windows
  • Particularités Win32/Win64

12.3.2 Configuration OpenGL Linux/Mesa

  • Installation des bibliothèques
  • Contexte OpenGL sous X11
  • Support Wayland

Sections suivantes

  • Rendu 2D et 3D de base
  • Textures et matériaux
  • Shaders GLSL
  • Animations et interactions
  • Optimisations avancées
  • Projets pratiques

Prérequis

Avant de continuer, assurez-vous de maîtriser :

Lazarus de base : Création de formulaires et composants
FreePascal : Syntaxe, types, procédures
Mathématiques 3D : Vecteurs, matrices (niveau lycée)
Concepts graphiques : Pixels, couleurs, coordonnées

Mathématiques nécessaires :

  • Trigonométrie de base (sin, cos, tan)
  • Vecteurs 3D et opérations
  • Matrices 4×4 (compréhension générale)

Objectifs d'apprentissage

À la fin de cette section 12.3, vous serez capable de :

✅ Configurer OpenGL sur Windows et Ubuntu/Linux
✅ Créer un contexte OpenGL avec TOpenGLControl
✅ Comprendre le pipeline de rendu OpenGL
✅ Dessiner des formes 2D et 3D simples
✅ Appliquer des transformations (translation, rotation, échelle)
✅ Gérer les textures et matériaux
✅ Utiliser les shaders GLSL basiques
✅ Optimiser les performances OpenGL
✅ Créer des applications OpenGL portables Windows/Linux
✅ Débugger et profiler des applications OpenGL


Conseils avant de commencer

Pour les débutants

  1. Commencez simple : Triangle, carré, puis objets 3D
  2. Expérimentez : Changez les valeurs pour voir l'effet
  3. Utilisez le débogueur : Vérifiez les erreurs OpenGL
  4. Lisez les erreurs : glGetError() pour diagnostiquer
  5. Patience : OpenGL a une courbe d'apprentissage

Pour les développeurs expérimentés

  1. Migration Delphi : Syntaxe similaire, API identique
  2. OpenGL moderne : Envisagez core profile + shaders
  3. Performance : Profilez avant d'optimiser
  4. Portabilité : Testez sur Windows ET Linux
  5. Alternatives : Considérez Vulkan pour projets complexes

Avertissements

⚠️ Pilotes GPU : OpenGL nécessite des pilotes graphiques à jour
⚠️ Compatibilité : Certaines fonctions avancées peuvent ne pas être supportées sur vieux matériel
⚠️ Thread-safety : OpenGL n'est PAS thread-safe par défaut
⚠️ Mémoire GPU : Les textures et buffers consomment de la VRAM
⚠️ Debug : Les erreurs OpenGL sont silencieuses (utilisez glGetError)


Prêt à commencer ?

Maintenant que vous comprenez les fondamentaux d'OpenGL et son intégration avec Lazarus, plongeons dans la configuration pratique sur Windows dans la section suivante !

Rappel : OpenGL est un outil puissant mais complexe. Prenez le temps de comprendre chaque concept avant de passer au suivant. La pratique est essentielle !

🚀 Let's render something amazing!

⏭️ Configuration OpenGL Windows