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

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 quatre 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 le 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 le cas d'un rayon de lumière réfléchi par un miroir 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 huit 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 ses 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 deuxième 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 Quatre 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 Quatre 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 Quatre 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 Quatre 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 Un 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 Trois 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 Un 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 Un paramètre : le coefficient d'atténuation constant.
 
glLightf ou glLighti GL_LINEAR_ATTENUATION Un paramètre : le coefficient d'atténuation linéaire (fonction de la distance).
 
glLightf ou glLighti GL_QUADRATIC_ATTENUATION Un paramètre : le coefficient 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 sphère à l'endroit où se trouve la lampe
#If VBA7 Then
Dim lQuad As LongPtr
#Else
Dim lQuad As Long
#End If
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

Notez l’utilisation de LongPtr à partir de VBA7 (Office 2010) pour gérer correctement les versions 64 bits ; en effet certaines fonctions glu renvoient des pointeurs.

Les fonctions glPushMatrix et glPopMatrix prennent ici toute leur importance.
On peut transformer 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 soient é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 n’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 longueur 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 œuvre.

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 Un paramètre qui détermine l'équation à utiliser pour gérer l'atténuation du brouillard.
Les valeurs possibles sont :
- GL_LINEAR pour une atténuation linéaire, 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éaire
Sélectionnez
glFogi GL_FOG_MODE, GL_LINEAR
glFogf ou glFogi GL_FOG_DENSITY Un 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 Un 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 Un 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 Un 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 Quatre 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 Un 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 écoulé pour calcul du frame rate
Private gElapsedTime As Long
' Nombre d'affichages 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

Function FonctionOpenGL()
' Chargement de freeGLUT
If Not LoadFreeGlut(CurrentProject.Path) Then
    MsgBox "Impossible de charger la bibliothèque freeGLUT"
    Exit Function
End If
' Initialisation de la bibliothèque
glutInit 0&, ""
' Initialisation du mode d'affichage
glutInitDisplayMode GLUT_RGBA Or GLUT_DOUBLE Or GLUT_DEPTH
' Définition de l'option de sortie de boucle
glutSetOption GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS
' Création d'une fenêtre
glutCreateWindow "Tutoriel fenêtre GLUT"
' Fonction d'affichage
glutDisplayFunc AddressOf CallBackDraw
' Fonctions de rappel clavier
glutSpecialFunc AddressOf CallBackSpecial
' Fonction de rappel molette de souris
glutMouseWheelFunc AddressOf CallBackMouseWheel
' Appel de la fonction d'initialisation
InitScene
' Fonction d'attente
glutTimerFunc 1000 / 50, AddressOf CallBackTimer, 0
' Boucle principale
glutMainLoop
End Function

' Fonction d'attente
Public Sub CallBackTimer(ByVal value As Long)
' Rappel de la fonction d'attente
glutTimerFunc 1000 / 50, AddressOf CallBackTimer, 0
' Rafraichir l'affichage si une fenêtre openGL est active
If glutGetWindow <> 0 Then glutPostRedisplay
End Sub

' Fonction d'affichage
Public Sub CallBackDraw()
' Appel de la fonction de rendu
Call Render
' Échange 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

' Fonction d'initialisation
Public Sub InitScene()
' Mode d'affichage = remplissage
glPolygonMode GL_FRONT_AND_BACK, GL_FILL
' 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

' Fonction de rendu
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 + 
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 sphère à l'endroit où se trouve la lampe
#If VBA7 Then
Dim lQuad As LongPtr
#Else
Dim lQuad As Long
#End If 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

' 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

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.