IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Découvrez OpenGL 1.1 en VB6/VBA

Image non disponible

Découvrez OpenGL 1.1 en VB6/VBA

Image non disponible


précédentsommairesuivant

XII. Les effets de lumière et de brouillard

XII-A. La lumière

XII-A-1. Les types de lumières

OpenGL gère 4 types de lumière :

Image non disponible   La lumière ambiante : GL_AMBIENT.
C'est la lumière de la lampe par défaut.
Elle semble venir de toutes les directions et est réfléchie dans toutes les directions.

Image non disponible   La lumière diffuse : GL_DIFFUSE.
Elle arrive d'une direction particulière et est réfléchie dans toutes les directions.
C'est la cas d'une lampe classique, une ampoule par exemple.

Image non disponible   La lumière spéculaire : GL_SPECULAR.
Elle arrive d'une direction particulière et est réfléchie dans une direction particulière.
C'est la cas d'un rayon de lumière réfléchi par un mirroir par exemple.

Image non disponible   La lumière émise : GL_EMISSION.
Elle est émise par un objet et non par une lampe.
La lumière émise n'éclaire pas les autres objets.

Les lumières peuvent se cumuler : par exemple, une lampe peut envoyer de la lumière ambiante et de la lumière diffuse en même temps.

XII-A-2. Les lampes

OpenGL gère 8 lampes, en plus de la lampe par défaut.
La lampe par défaut est une lumière ambiante, on le voit bien : notre cube est éclairé sur toutes ces faces comme si la lumière venait de toutes les directions.

Si on souhaite gérer notre propre lumière, il faut d'abord activer l'éclairage :
glEnable GL_LIGHTING
(ceci désactive la lampe par défaut).

Puis activer les lampes que nous souhaitons gérer :
glEnable GL_LIGHTn avec n de 0 à 7.

Les fonctions glLight* permettent de gérer les attributs des lampes :
- Le premier paramètre est le numéro de la lampe, de GL_LIGHT0 à GL_LIGHT7.
- Le second paramètre est le code de l'attribut à modifier.
- Le troisième paramètre est la valeur à affecter à l'attribut.

Les fonctions en suffixe f demandent un paramètre de type single.
Les fonctions en suffixe i demandent un paramètre de type long.
Les fonctions en suffixe fv demandent un paramètre de type tableau de single.
Les fonctions en suffixe iv demandent un paramètre de type tableau de long.

Fonction Code de l'attribut Valeur Exemple
glLightfv ou glLightiv GL_AMBIENT 4 paramètres RGBA qui déterminent l'intensité et la couleur de la lumière.
Si on utilise des paramètres long avec glLightiv, les valeurs sont recalculées linéairement pour que le maxi des composantes soit égal à 1.
Ces paramètres peuvent être négatifs (de -1 à 1).
Exemple de lampe bleue
Sélectionnez

Dim lColor(1 To 4) As Single
lColor(1) = 0
lColor(2) = 0
lColor(3) = 1
lColor(4) = 1
glLightfv GL_LIGHT0, GL_AMBIENT, lColor(1)
                            
glLightfv ou glLightiv GL_DIFFUSE 4 paramètres RGBA qui déterminent l'intensité et la couleur de la lumière.
Même utilisation que GL_AMBIENT
 
glLightfv ou glLightiv GL_SPECULAR 4 paramètres RGBA qui déterminent l'intensité et la couleur de la lumière.
Même utilisation que GL_AMBIENT
 
glLightfv ou glLightiv GL_POSITION 4 paramètres x,y,z et w qui déterminent la position de la lampe.
- Si w vaut 0, la lampe est directionnelle : x,y,z est un vecteur qui définit la direction de la lumière.
- Si w vaut 1, la lampe est positionnelle : x,y,z définit la position de la source de lumière.
Par défaut, la lampe est directionnelle avec un vecteur (0,0,1).
Exemple de lampe positionnelle
Sélectionnez

Dim lposition(1 To 4) As Single
lposition(1) = 10
lposition(2) = 10
lposition(3) = 5
lposition(4) = 1
glLightfv GL_LIGHT0, GL_POSITION, lposition(1)
glLightf ou glLighti GL_SPOT_CUTOFF 1 paramètre qui définit l'angle d'émission de la lumière.
La valeur est de 180° par défaut.
Les valeurs possibles vont de 0 à 90; la valeur 180 est acceptée.
 
glLightfv ou glLightiv GL_SPOT_DIRECTION 3 paramètres qui déterminent la direction d'un spot.
La direction par défaut est (0,0,-1).
Cet attribut n'est utile que si l'angle d'ouverture de la lampe (GL_SPOT_CUTOFF) n'est pas 180° (sa valeur par défaut)
 
glLightf ou glLighti GL_SPOT_EXPONENT 1 paramètre qui définit l'atténuation angulaire.
Valeurs de 0 à 128.
L'atténuation vaut 0 par défaut et correspond à une répartition uniforme de la lumière.
Plus la valeur est élevée, plus la lumière est concentrée au centre.
 
glLightf ou glLighti GL_CONSTANT_ATTENUATION 1 paramètre : le coëfficient d'atténuation constant
 
glLightf ou glLighti GL_LINEAR_ATTENUATION 1 paramètre : le coëfficient d'atténuation linéraire (fonction de la distance)
 
glLightf ou glLighti GL_QUADRATIC_ATTENUATION 1 paramètre : le coëfficient d'atténuation quadratique (fonction de la distance au carré)
 

XII-A-3. Mise en pratique

Nous allons ajouter une lampe diffuse qui tourne autour du cube.

Initialisons d'abord l'éclairage, dans la fonction InitScene :

Initialisation de l'éclairage
Sélectionnez

' Initialisation de l'éclairage
glEnable GL_LIGHTING
glEnable GL_LIGHT0


On a activé la lampe GL_LIGHT0.

Par défaut, la lampe émet une faible lumière ambiante.
On voit très légèrement le cube.
Donnons lui en plus une lumière diffuse, à la suite du code précédent :

Ajout d'une lumière diffuse
Sélectionnez

' Ajout d'une lumière diffuse
Dim lColor(1 To 4) As Single
lColor(1) = 2
lColor(2) = 2
lColor(3) = 2
lColor(4) = 1
glLightfv GL_LIGHT0, GL_DIFFUSE, lColor(1)


La lampe émet maintenant une lumière blanche (2,2,2).
Remarquez qu'on peut utiliser des valeurs supérieures à 1.
Par défaut, elle éclaire de l'avant vers le fond.

Image non disponible

Si vous tournez autour du cube, vous verrez que l'arrière n'est pas éclairé.

Le cube est blanc, car il est éclairé par une lumière blanche.
On a perdu les couleurs du cube.
Pour les retrouver, activer la coloration des matériaux dans l'initialisation de l'éclairage :

Active la coloration des matériaux
Sélectionnez

' Active la coloration des matériaux
glEnable GL_COLOR_MATERIAL

On retrouve les couleurs du cube.

Pour faire tourner la lampe autour du cube on définit une variable en en-tête du module pour conserver l'angle de rotation de la lampe.

En en-tête de module
Sélectionnez

' RotationY de la lampe
Private gLightRotate As Double


Puis on positionne la lampe dans la fonction Render, juste après l'appel à glClear.

Positionne la lampe
Sélectionnez

' Positionne la lampe
gLightRotate = gLightRotate + 0.03
Dim lposition(1 To 4) As Single
lposition(1) = 3 * Cos(gLightRotate)
lposition(2) = 0
lposition(3) = 3 * Sin(gLightRotate)
lposition(4) = 1
glLightfv GL_LIGHT0, GL_POSITION, lposition(1)


La lampe tourne mais on ne voit pas vraiment où elle se trouve et si l'éclairage est correct.

Pour matérialiser la lampe, on va dessiner une petite sphère.
Pour dessiner une sphère, on utilise la fonction gluSphere qui nous facilite la tâche.
Ajoutez le code de dessin de la sphère juste après le positionnement de la lampe :

Matérialise la lampe avec une sphère
Sélectionnez

' Dessine une sphere à l'endroit  se trouve la lampe
Dim lQuad As Long
glPushMatrix
glColor3VB vbYellow
glTranslated 3 * Cos(gLightRotate), 0, 3 * Sin(gLightRotate)
lQuad = gluNewQuadric
gluQuadricOrientation lQuad, GLU_INSIDE
gluSphere lQuad, 0.5, 20, 15
gluDeleteQuadric lQuad
glPopMatrix


Les fonctions glPushMatrix et glPopMatrix prennent ici toute leur importance.
On peut tranformer la sphère et le cube indépendamment en sauvegardant puis en restaurant la matrice de modélisation-visualisation.

Notez qu'on a défini une sphère de couleur jaune, de taille 0.5, avec 20 divisions pour les longitudes et 15 divisions pour les latitudes.
On a également modifié l'orientation de la sphère (GLU_INSIDE) de manière à ce que les faces soit éclairées (sinon une lumière à l'intérieur de la sphère ne l'éclaire pas à l'extérieur).

La sphère est créée centrée sur l'origine.
Nous la déplaçons à l'endroit où se situe la lampe avec la fonction glTranslated.

Testons notre éclairage :

Image non disponible

On remarque un problème : la lampe est à droite et commence à éclairer la face gauche en violet.
Il se trouve qu'on a pas défini de normale lors du dessin du cube.

Il faut ajouter une normale pour chaque face du cube.

Le dessin du cube avec les normales
Sélectionnez

' Début de la primitive pour le cube
glBegin GL_QUADS
    ' Face du haut = vert
    Call glColor3d(0, 1, 0)
    Call glNormal3d(0, 1, 0)
    Call glVertex3d(1, 1, -1)
    Call glVertex3d(-1, 1, -1)
    Call glVertex3d(-1, 1, 1)
    Call glVertex3d(1, 1, 1)
    ' Face du bas = orange
    Call glColor3d(1, 0.5, 0)
    Call glNormal3d(0, -1, 0)
    Call glVertex3f(-1, -1, -1)
    Call glVertex3f(1, -1, -1)
    Call glVertex3f(1, -1, 1)
    Call glVertex3f(-1, -1, 1)
    ' Face de derrière = rouge
    Call glColor3d(1, 0, 0)
    Call glNormal3d(0, 0, -1)
    Call glVertex3f(1, -1, -1)
    Call glVertex3f(-1, -1, -1)
    Call glVertex3f(-1, 1, -1)
    Call glVertex3f(1, 1, -1)
    ' Face de devant = jaune
    Call glColor3d(1, 1, 0)
    Call glNormal3d(0, 0, 1)
    Call glVertex3f(-1, -1, 1)
    Call glVertex3f(1, -1, 1)
    Call glVertex3f(1, 1, 1)
    Call glVertex3f(-1, 1, 1)
    ' Face de gauche = violet
    Call glColor3d(1, 0, 1)
    Call glNormal3d(-1, 0, 0)
    Call glVertex3f(-1, 1, 1)
    Call glVertex3f(-1, 1, -1)
    Call glVertex3f(-1, -1, -1)
    Call glVertex3f(-1, -1, 1)
    ' Face de droite = bleu
    Call glColor3d(0, 0, 1)
    Call glNormal3d(1, 0, 0)
    Call glVertex3f(1, 1, -1)
    Call glVertex3f(1, 1, 1)
    Call glVertex3f(1, -1, 1)
    Call glVertex3f(1, -1, -1)
glEnd


Comme pour les couleurs on définit une normale par face, mais la normale s'applique à chaque vertice de la face.

Pour que l'éclairage soit correct, il faut que les normales aient une longeur de 1.
Ce qui est le cas pour nos normales lors de leur définition.
Mais lorsqu'on redimensionne la scène, où si on définit des normales plus complexes (non parallèles à un axe), elles peuvent ne plus être à la bonne taille.
Utilisez la commande glEnable GL_NORMALIZE à l'initialisation pour qu'openGL redimensionne les normales avant éclairage.

Testons à nouveau l'éclairage avec les normales :

Image non disponible

Voilà qui est mieux, les faces sont éclairées correctement.

En y regardant de plus près, on voit que chaque face du cube est éclairée progressivement.
C'est le comportement standard, que l'on peut changer avec la fonction glShadeModel.
- glShadeModel GL_FLAT permet de colorier tout le polygone uniformément.
C'est plus rapide mais moins joli.
- glShadeModel GL_SMOOTH permet de colorier le polygone progressivement.
C'est le comportement par défaut.

XII-B. Le brouillard

Le brouillard est très facile à mettre en oeuvre.

Pour activer le brouillard : glEnable GL_FOG

Les fonctions glFog* permettent de gérer les attributs du brouillard :
- Le premier paramètre est le code de l'attribut à modifier.
- Le second paramètre est la valeur à affecter à l'attribut.

Les fonctions en suffixe f demandent un paramètre de type single.
Les fonctions en suffixe i demandent un paramètre de type long.
Les fonctions en suffixe fv demandent un paramètre de type tableau de single.
Les fonctions en suffixe iv demandent un paramètre de type tableau de long.

Fonction Code de l'attribut Valeur Exemple
glFogf ou glFogi GL_FOG_MODE 1 paramètre qui détermine l'équation à utilisée pour gérer l'atténuation du brouillard.
Les valeurs possibles sont :
- GL_LINEAR pour une atténuation linéraire, c'est le plus rapide.
- GL_EXP pour une atténuation exponentielle, c'est le mode par défaut.
- GL_EXP2 pour une atténuation exponentielle au carré.
Exemple d'atténuation linéraire
Sélectionnez

glFogi GL_FOG_MODE, GL_LINEAR
glFogf ou glFogi GL_FOG_DENSITY 1 paramètre qui détermine la densité du brouillard.
La valeur doit être positive.
La densité par défaut est de 1.
Exemple de densité de brouillard
Sélectionnez

glFogf GL_FOG_DENSITY, 0.2
glFogf ou glFogi GL_FOG_START 1 paramètre qui détermine la distance où commence le brouillard.
C'est une distance par rapport à la caméra.
Valable pour un mode GL_LINEAR seulement.
Exemple de début du brouillard
Sélectionnez

glFogf GL_FOG_START, 5
glFogf ou glFogi GL_FOG_END 1 paramètre qui détermine la distance où s'arrête le brouillard.
C'est une distance par rapport à la caméra.
Valable pour un mode GL_LINEAR seulement.
Exemple de fin du brouillard
Sélectionnez

glFogf GL_FOG_END, 10
glFogf ou glFogi GL_FOG_INDEX 1 paramètre qui détermine l'index de la couleur du brouillard.
Uniquement si la fenêtre a été créée avec des couleurs indexées (GLUT_INDEX).
Exemple de couleur indexée du brouillard
Sélectionnez

glFogi GL_FOG_INDEX, 10
glFogfv ou glFogiv GL_FOG_COLOR 4 paramètres qui déterminent la couleur RGBA du brouillard.
Uniquement si la fenêtre a été créée avec des couleurs RGB (GLUT_RGB ou GLUT_RGBA).
Par défaut, le brouillard est noir (0,0,0,0).
Exemple de brouillard gris
Sélectionnez

Dim lfogcolor(1 To 4) As Single
lfogcolor(1) = 0.7
lfogcolor(2) = 0.7
lfogcolor(3) = 0.7
lfogcolor(4) = 1
glFogfv GL_FOG_COLOR, lfogcolor(1)
glHint GL_FOG_HINT 1 paramètre qui détermine la qualité du brouillard.
Peut valoir GL_FASTEST, GL_NICEST, ou GL_DONT_CARE.
Exemple de brouillard moins beau mais plus rapide
Sélectionnez

glHint GL_FOG_HINT, GL_FASTEST


Ajoutons un brouillard gris à notre scène, dans la fonction InitScene :

Ajout du brouillard
Sélectionnez

' Initialisation du brouillard
Dim lfogcolor(1 To 4) As Single
glEnable GL_FOG
lfogcolor(1) = 0.7
lfogcolor(2) = 0.7
lfogcolor(3) = 0.7
lfogcolor(4) = 1
glFogfv GL_FOG_COLOR, lfogcolor(1)
glFogi GL_FOG_MODE, GL_LINEAR
glFogf GL_FOG_START, 7
glFogf GL_FOG_END, 10
glFogf GL_FOG_DENSITY, 0.1
glHint GL_FOG_HINT, GL_NICEST

Et voici notre cube dans le brouillard :

Image non disponible

XIII. Rappel du code complet

Un rappel du contenu du module VB à ce stade du tutoriel, avec la lumière et le brouillard :

Rappel du code complet
Sélectionnez

Option Explicit

' Temps à attendre pour le prochaine affichage
Private gWaitTime As Long
' Temps écoulé pour calcul du frame rate
Private gElapsedTime As Long
' Nombre d'affichage pour calcul du frame rate
Private gDisplayCount As Long
' RotationX
Private gRotateX As Double
' RotationY
Private gRotateY As Double
' Zoom
Private gZoom As Double
' RotationY de la lampe
Private gLightRotate As Double

' Fonction principale
Function FonctionOpenGL()
' Chargement de freeglut
If LoadLibrary(CurrentProject.Path & "\freeglut.dll") = 0 Then
    MsgBox "Impossible de charger la librairie freeglut"
    Exit Function
End If
' Initialisation de la librairie
glutInit 0&, ""
' Initialisation du mode d'affichage
glutInitDisplayMode GLUT_RGBA Or GLUT_DOUBLE Or GLUT_DEPTH
' Création d'une fenêtre
glutCreateWindow "Tutoriel fenêtre GLUT"
' Définition de l'option de sortie de boucle
glutSetOption GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS
' Fonction d'affichage
glutDisplayFunc AddressOf CallBackDraw
' Fonction d'attente
glutIdleFunc AddressOf CallBackIdle
' Fonctions de rappel clavier
glutSpecialFunc AddressOf CallBackSpecial
' Fonction de rappel molette de souris
glutMouseWheelFunc AddressOf CallBackMouseWheel
' Appel de la fonction d'initialisation
InitScene
' Boucle principale
glutMainLoop
End Function

' Fonction d'affichage
Public Sub CallBackDraw()
' Appel de la fonction de rendu
Call Render
' Echange les buffers
glutSwapBuffers
' Calcul et affichage du frame rate
gDisplayCount = gDisplayCount + 1
If gDisplayCount = 100 Then
    glutSetWindowTitle "Frame rate : " & format(gDisplayCount / (glutGet(GLUT_ELAPSED_TIME) - gElapsedTime) * 1000, "0,0")
    gDisplayCount = 0
    gElapsedTime = glutGet(GLUT_ELAPSED_TIME)
End If
End Sub

' Procédure de rappel attente
Public Sub CallBackIdle()
    Dim lTimer As Long
    ' Temps présent
    lTimer = glutGet(GLUT_ELAPSED_TIME)
    ' Si temps présent >= au temps attendu
    If lTimer >= gWaitTime Then
        ' Rrafraichir l'affichage
        glutPostRedisplay
        ' n affichages par seconde
        gWaitTime = lTimer + (1000 / 50)
    End If
End Sub

' Gestion du clavier
Public Sub CallBackSpecial(ByVal key As Long, ByVal x As Long, ByVal y As Long)
Select Case key
    Case GLUT_KEY_LEFT
        gRotateY = gRotateY - 10
    Case GLUT_KEY_RIGHT
        gRotateY = gRotateY + 10
    Case GLUT_KEY_UP
        gRotateX = gRotateX - 10
    Case GLUT_KEY_DOWN
        gRotateX = gRotateX + 10
End Select
End Sub

' Gestion de la molette de la souris
Public Sub CallBackMouseWheel(ByVal wheel As Long, ByVal direction As Long, ByVal x As Long, ByVal y As Long)
gZoom = gZoom + direction
End Sub

' Initialisation de la scène
Public Sub InitScene()
' Initialisation du temps déclencheur de l'affichage
gWaitTime = glutGet(GLUT_ELAPSED_TIME)
' Tests de profondeur
glEnable GL_DEPTH_TEST
glDepthFunc GL_LEQUAL
' Initialisation des variables de visualisation
gRotateX = 0
gRotateY = 0
gZoom = 10
' Initialisation de l'éclairage
glEnable GL_LIGHTING
glEnable GL_LIGHT0
' Ajout d'une lumière diffuse
Dim lColor(1 To 4) As Single
lColor(1) = 2
lColor(2) = 2
lColor(3) = 2
lColor(4) = 1
glLightfv GL_LIGHT0, GL_DIFFUSE, lColor(1)
' Active la coloration des matériaux
glEnable GL_COLOR_MATERIAL
' Initialisation du brouillard
Dim lfogcolor(1 To 4) As Single
glEnable GL_FOG
lfogcolor(1) = 0.7
lfogcolor(2) = 0.7
lfogcolor(3) = 0.7
lfogcolor(4) = 1
glFogfv GL_FOG_COLOR, lfogcolor(1)
glFogi GL_FOG_MODE, GL_LINEAR
glFogf GL_FOG_START, 7
glFogf GL_FOG_END, 10
glFogf GL_FOG_DENSITY, 0.1
glHint GL_FOG_HINT, GL_NICEST
End Sub

' Rendu de la scène
Public Sub Render()
' Passage en matrice de projection
glMatrixMode GL_PROJECTION
' Initialisation de la matrice
glLoadIdentity
' Définition de la perspective
gluPerspective 45, 1, 0.1, 100
' Passage en matrice de modélisation-visualisation
glMatrixMode GL_MODELVIEW
' Initialisation de la matrice
glLoadIdentity
' Position de la caméra
gluLookAt 0, 0, gZoom, 0, 0, 0, 0, 1, 0
glRotated gRotateX, 1, 0, 0
glRotated gRotateY, 0, 1, 0
' Vide les buffers couleur et profondeur
glClear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
' Positionne la lampe
gLightRotate = gLightRotate + 0.03
Dim lposition(1 To 4) As Single
lposition(1) = 3 * Cos(gLightRotate)
lposition(2) = 0
lposition(3) = 3 * Sin(gLightRotate)
lposition(4) = 1
glLightfv GL_LIGHT0, GL_POSITION, lposition(1)
' Dessine une sphere à l'endroit  se trouve la lampe
Dim lQuad As Long
glPushMatrix
glColor3VB vbYellow
glTranslated 3 * Cos(gLightRotate), 0, 3 * Sin(gLightRotate)
lQuad = gluNewQuadric
gluQuadricOrientation lQuad, GLU_INSIDE
gluSphere lQuad, 0.5, 20, 15
gluDeleteQuadric lQuad
glPopMatrix
' Sauvegarde la matrice
glPushMatrix
' Rotation du cube
glRotated 30, 1, 1, 1
' Début de la primitive pour le cube
glBegin GL_QUADS
    ' Face du haut = vert
    Call glColor3d(0, 1, 0)
    Call glNormal3d(0, 1, 0)
    Call glVertex3d(1, 1, -1)
    Call glVertex3d(-1, 1, -1)
    Call glVertex3d(-1, 1, 1)
    Call glVertex3d(1, 1, 1)
    ' Face du bas = orange
    Call glColor3d(1, 0.5, 0)
    Call glNormal3d(0, -1, 0)
    Call glVertex3f(-1, -1, -1)
    Call glVertex3f(1, -1, -1)
    Call glVertex3f(1, -1, 1)
    Call glVertex3f(-1, -1, 1)
    ' Face de derrière = rouge
    Call glColor3d(1, 0, 0)
    Call glNormal3d(0, 0, -1)
    Call glVertex3f(1, -1, -1)
    Call glVertex3f(-1, -1, -1)
    Call glVertex3f(-1, 1, -1)
    Call glVertex3f(1, 1, -1)
    ' Face de devant = jaune
    Call glColor3d(1, 1, 0)
    Call glNormal3d(0, 0, 1)
    Call glVertex3f(-1, -1, 1)
    Call glVertex3f(1, -1, 1)
    Call glVertex3f(1, 1, 1)
    Call glVertex3f(-1, 1, 1)
    ' Face de gauche = violet
    Call glColor3d(1, 0, 1)
    Call glNormal3d(-1, 0, 0)
    Call glVertex3f(-1, 1, 1)
    Call glVertex3f(-1, 1, -1)
    Call glVertex3f(-1, -1, -1)
    Call glVertex3f(-1, -1, 1)
    ' Face de droite = bleu
    Call glColor3d(0, 0, 1)
    Call glNormal3d(1, 0, 0)
    Call glVertex3f(1, 1, -1)
    Call glVertex3f(1, 1, 1)
    Call glVertex3f(1, -1, 1)
    Call glVertex3f(1, -1, -1)
glEnd
' Restaure la matrice
glPopMatrix
End Sub

précédentsommairesuivant

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 © 2017 Thierry GASPERMENT. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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. Droits de diffusion permanents accordés à Developpez LLC.