La transparence

Jeff Molofee (NeHe)

Traducteur

Jean Christophe Beyler

Un programmeur du site Hypercosm a demandé s'il pouvait écrire un tutoriel sur le blending (ou mélange de couleur). Cette leçon est donc un tutoriel de ce monsieur. Cette partie est en fait la continuité de la leçon sept. Le Blending (ou mélange) est un effet très pratique. L'auteur se prénomme Tom Stanis. ♪

- Titre : La transparence

- Auteur : Jeff Molofee (NeHe)

- Traducteur : Jean Christophe Beyler

- Parution : 23 mars 2007

- Mise à jour : 19 décembre 2012

- Licence : 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 ® 2007 Nehe Gamedev.net. 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.

Sommaire

- I. Contributions

- II. Tutoriel

- II-A. Équation de mélange

- II-B. Faire des mélanges de couleurs avec OpenGL

- II-C. Canal alpha d'une texture

- III. Téléchargements

- IV. Remerciements

- V. Liens

I - Contributions

Nous recherchons toujours des traducteurs pour finir ce projet de traduction des articles de NeHe. Votre aide serait appréciée ! Vous êtes intéressé ? Alors contactez-nous à l'adresse suivante : nehe@redaction-developpez.com.

II - Tutoriel

La plupart des effets spéciaux en OpenGL utilisent une sorte de mélange de couleurs. Ce mélange est effectué en combinant la couleur d'un pixel donné avec ce qui se trouve déjà à l'écran. La façon dont les couleurs sont mélangées se base sur la valeur alpha des deux pixels, et/ou la fonction de mélange utilisée. L'alpha est généralement la quatrième et dernière composante d'une couleur. Dans le passé, vous utilisiez GL_RGB pour spécifier une couleur avec trois composantes. GL_RGBA peut être utilisé pour aussi spécifier le canal alpha. De plus, nous utiliserons glColor4f au lieu de glColor3f.

La plupart des personnes considèrent le canal Alpha comme étant le degré d'opacité d'un matériel. Une valeur de 0.0 veut dire que l'objet est entièrement transparent et 1.0 que l'objet est entièrement opaque.

II-A - Équation de mélange

Si vous êtes inconfortable avec les maths et voulez simplement voir comment utiliser la transparence, passez à la section suivante. Si vous voulez comprendre comment sont gérés les calculs de mélange de couleurs, cette section est pour vous.

Formule pour les couleurs

(Rs * Sr + Rd * Dr, Gs * Sg + Gd * Dg, Bs * Sb + Bd * Db, As * Sa + Ad * Da)

OpenGL va calculer le résultat du mélange de deux pixels en se basant sur l'équation précédente. Les variables s et d spécifient les pixels source et destination (donc Rs est la composante rouge du pixel source et Gd est la composante verte du pixel destination…). Les variables S et D représentent les facteurs de mélange. Ces valeurs indiquent comment vous voulez mélanger les deux pixels. Les valeurs les plus courantes pour S et D sont (As, As, As As) (donc la valeur Alpha du pixel source) pour S et (1 - As, 1 - As, 1 - As, 1 - As) (donc 1 moins la valeur Alpha du pixel source) pour D. Ceci va donner une équation de mélange qui ressemblera à :

Formule pour la transparence

(Rs * As + Rd * (1 - As), Gs * As + Gd * (1 - As), Bs * As + Bd * (1 - As), As * As + Ad * (1 - As))

Cette équation va permettre d'avoir un effet de transparence.

II-B - Faire des mélanges de couleurs avec OpenGL

On active le mélange comme tout le reste (avec la fonction glEnable). Ensuite, on définit l'équation, on désactive l'écriture dans le tampon de profondeur (puisque nous voulons que les objets qui sont derrière les formes transparentes soient encore dessinés). Ceci n'est pas vraiment la bonne façon de faire des mélanges de couleurs, mais dans des projets simples, cela suffit. Rui Martins ajoute : pour le faire correctement, il faut d'abord dessiner toute la scène et ensuite dessiner tous les polygones transparents (avec le canal alpha < 1.0). L'ordre du rendu doit se faire dans l'ordre inverse de la profondeur (donc le polygone le plus lointain doit être dessiné d'abord). Ceci est dû à la différence de résultats dépendant de l'ordre de rendu de deux polygones transparents (1 et 2). Par exemple, en supposant que 1 est plus proche de la caméra, pour être correct, il faudrait dessiner le polygone 2 et seulement ensuite le polygone 1. Si on regarde le rendu, comme dans la réalité, la lumière venant de derrière ces deux polygones (qui sont transparents) doit passer par 2 avant de passer par 1. Vous devez donc trier les polygones transparents par profondeur et les dessiner après tout le reste de la scène avec le test de profondeur mis en place. C'est une technique plus lourde, mais la meilleure si vous souhaitez un résultat correct.

On utilise le code du dernier tutoriel. Nous allons commencer par ajouter deux nouvelles variables au début de ce code. Je vais remettre toute cette partie du code pour être plus clair.

Inclusion, variables globales et déclaration de prototype

#include <windows.h>                 // Fichier d'en-tete pour Windows
#include <stdio.h>                   // Fichier d'en-tete pour l'entree/sortie standard
#include <gl\gl.h>                   // Fichier d'en-tete pour la bibliotheque OpenGL
#include <gl\glu.h>                  // Fichier d'en-tete pour la bibliotheque GLu
#include <gl\glaux.h>                // Fichier d'en-tete pour la bibliotheque GLaux

HDC       hDC=NULL;                  // Contexte de fenetre
HGLRC     hRC=NULL;                  // Contexte de rendu permanent
HWND      hWnd=NULL;                 // Contient un identifiant de fenêtre
HINSTANCE hInstance;                 // Contient une instance de l'application

bool    keys[256];                   // Tableau utilisé pour la gestion du clavier
bool    active=TRUE;                 // Window Active Flag Set To TRUE By Default
bool    fullscreen=TRUE;             // Variable pour le plein écran mis a TRUE par defaut
bool    light;                       // Lumiere ON/OFF
bool    blend;                       // Melange de couleurs (Nouveau)
bool    lp;                          // L appuye ?
bool    fp;                          // F appuye ?
bool    bp;                          // B appuye ? (Nouveau)
GLfloat xrot;                        // X Rotation
GLfloat yrot;                        // Y Rotation
GLfloat xspeed;                      // X Rotation Vitesse
GLfloat yspeed;                      // Y Rotation Vitesse
GLfloat z=-5.0f;                     // Profondeur dans l'ecran
GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };    // Valeurs de la lumiere ambiente
GLfloat LightDiffuse[]=  { 1.0f, 1.0f, 1.0f, 1.0f };   // Valeurs de la lumiere diffuse
GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };   // Position de la lumiere
GLuint  filter;                      // Utiliser quel filtre ?
GLuint  texture[3];                  // Stockage pour 3 textures
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  // Declaration de WndProc

Allez dans la fonction LoadGLTextures. Trouvez la ligne où se trouve if (TextureImage[0]=LoadBMP(« Data/Crate.bmp »)). Utilisez la ligne ci-dessous à la place. Nous allons utiliser une texture représentant un vitrail pour ce tutoriel.

Chargement d'une image

if (TextureImage[0]=LoadBMP("Data/glass.bmp"))  // Charger la texture ( MODIFIE )

Ajoutez les deux lignes suivantes quelque part dans la fonction InitGL. La première ligne met en place une brillance de l'objet au maximum avec 50 % d'alpha (opacité). Ceci veut dire que lorsque le mélange de couleur sera mis en place, l'objet sera à 50 % transparent. La deuxième ligne met en place le type de mélange que nous allons utiliser.

Rui Martins ajoute : une valeur de 0.0 veut dire que le matériel serait entièrement transparent. Une valeur de 1.0 veut dire qu'il serait entièrement opaque.

Mise en place du canal alpha et de la fonction de mélange

// Brillance au maximum, 50 % Alpha ( NOUVEAU )
glColor4f(1.0f,1.0f,1.0f,0.5f);
// Fonction de melange pour transparence dependant de la valeur source alpha(Nouveau)
glBlendFunc(GL_SRC_ALPHA,GL_ONE);

Si vous regardez le code qui suit, il peut être retrouvé à la fin de la septième leçon.

Gestion de la flèche gauche

if (keys[VK_LEFT])   // Est-ce qu'on appuie sur la fleche gauche
{
yspeed-=0.01f;     // Si oui, décrémenter la vitesse Y
}

En dessous de ce code, nous voulons ajouter les lignes suivantes. Les lignes à ajouter regardent si la touche 'B' a été appuyée. Si c'est le cas, le programme vérifie s'il est en train de mélanger les couleurs ou non. Si cette option est active, il la désactive, sinon il l'active.

Gestion de la touche 'B'

if (keys['B'] && !bp)     // Est-ce que B est appuyee et bp est a FALSE ?
{
bp=TRUE;                // Si oui, bp devient TRUE
blend = !blend;         // Changer la valeur de blend (entre TRUE et FALSE)
if(blend)               // Est-ce qu'on melange les couleurs ?
{
glEnable(GL_BLEND);    // Activation du melange des couleurs
glDisable(GL_DEPTH_TEST); // Desactivation du test de profondeur
}
else                    // Sinon
{
glDisable(GL_BLEND);   // Desactivation du melange des couleurs
glEnable(GL_DEPTH_TEST); // Activation du test de profondeur
}
}
if (!keys['B'])          // Est-ce que B a ete appuye ?
{
bp=FALSE;               // bp devient faux si c'est le cas
}

Mais comment spécifier la couleur que nous utilisons avec une texture ? C'est simple, en modulant la texture avec la couleur courante, chaque pixel de la texture sera multiplié par la couleur. Donc, si la couleur à utiliser est (0.5, 0.6, 0.4) nous allons multiplier la couleur de chaque pixel de la texture par (0.5, 0.6, 0.4) (alpha est supposé à 1.0 si ce n'est pas spécifié).

C'est tout ! Le mélange de couleurs est assez simple à faire en OpenGL.

Remarque (13/11/99)

J'ai (Nehe) modifié le code du mélange pour que le résultat ressemble plus au résultat attendu. En utilisant des valeurs Alpha pour la source et la destination, cela provoque des effets d'irréalisme. Les faces du cube qui se retrouvent derrière et sur les côtés sont plus sombres que ce qu'elles devraient être. Ce que je fais ici n'est probablement pas la meilleure solution, mais elle fonctionne et le résultat semble correct lorsque la lumière est active. Merci à Tom pour le code initial, sa technique pour le mélange était correcte, mais les gens s'attendaient à quelque chose de plus attractif.

II-C - Canal alpha d'une texture

La valeur alpha utilisée pour la transparence peut être récupérée par un fichier image avec les couleurs. Pour le faire, il suffit de rajouter un canal alpha à l'image que vous voulez utiliser et mettre GL_RGBA pour le format à passer aux appels glTexImage2D.

Tom Stanis

Enfin, voici une petite image de ce que vous devez voir :

Image de l'application

Jeff Molofee (NeHe)

III - Téléchargements

Compte tenu du nombre de versions de codes sources pour les tutoriels nehe, nous les laissons en anglais. En principe, si vous avez compris le code présenté dans ce tutoriel (et les tutoriels antérieurs), vous n'aurez pas de mal à le comprendre :

- Borland C++ Builder 6(Conversion par Christian Kindahl)

- C#(Conversion par Brian Holley)

- Code Warrior 5.3(Conversion par Scott Lupton)

- CygWin(Conversion par Stephan Ferraro)

- D(Conversion par Familia Pineda Garcia)

- Delphi(Conversion par Michal Tucek)

- Dev C++(Conversion par Dan)

- Euphoria(Conversion par Evan Marshall)

- Game GLUT(Conversion par Milikas Anastasios)

- GLUT(Conversion par Andy Restad)

- Irix(Conversion par Lakmal Gunasekara)

- Java(Conversion par Jeff Kirby)

- Jedi-SDL(Conversion par Dominique Louis)

- JOGL(Conversion par Pepijn Van Eeckhoudt)

- LCC Win32(Conversion par Robert Wishlaw)

- Linux(Conversion par Richard Campbell)

- Linux GLX(Conversion par Mihael Vrbanec)

- Linux SDL(Conversion par Ti Leggett)

- LWJGL(Conversion par Mark Bernard)

- Mac OS(Conversion par Anthony Parker)

- Mac OS X/Cocoa(Conversion par Bryan Blackburn)

- MASM(Conversion par Nico (Scalp))

- VC++/OpenIL(Conversion par Denton Woods)

- Pelles C(Conversion par Pelle Orinius)

- Power Basic(Conversion par Angus Law)

- Python(Conversion par Ryan Showalter)

- Scheme(Conversion par Brendan Burns)

- Solaris(Conversion par Lakmal Gunasekara)

- Visual Basic(Conversion par Peter de Tagyos)

- Visual Fortran(Conversion par Jean-Philippe Perois)

- Visual Studio

- Visual Studio NET(Conversion par Grant James)

IV - Remerciements

Merci à Fiquet et à jc_cornic pour leur relecture.

V - Liens

Sommaire

Tutoriel précédent : Les filtres et l'éclairage

Tutoriel prochain : Déplacer un bitmap en 3D