Plusieurs fois déjà des couleurs ont été présentée sous forme RGBA : rouge, vert, bleu et alpha. Si les trois premières coordonnées sont évidentes, la quatrième, quant à elle, sert à indiquer la « transparence ».
Si pour l’instant rien n’a été dit sur les valeurs de l’alpha, c’est simplement parce que par défaut OpenGL s’en fiche. Pour activer le canal alpha, il faut appeler comme d’habitude glEnable :
glEnable(GL_BLEND) ;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ; // expliqué après
Ensuite il suffit de changer la valeur de A suivant la transparence.
Il s'agit, toujours du même cube, mais dont les côtés sont maintenant transparents.
void CALLBACK Main_part(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
drawFloor();
glPushMatrix();
//initialisation de la transparence
glEnable(GL_BLEND);
//la couleur de l'objet va être (1-alpha_de_l_objet) * couleur du fond et (le_reste * couleur originale)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTranslatef(0.0f, -2.0f, 5.0f);
glRotatef((80.0f), -0.5f, 0.3f, -0.8f);
glRotatef((10.0f), 0.5f, -0.3f, 0.8f);
glCallList(cube);
//on désactive la transparence
glDisable(GL_BLEND);
glPopMatrix();
auxSwapBuffers();
}
void init()
{
//C'est la partie la plus importante
//Les couleurs sont définies avec un alpha de 0.25
//qui va servir dans le calcul de la transparence
//Rappel : 0 = transparent, 1 = opaque
GLfloat Rouge[] = {0.8f, 0.0f, 0.0f, 0.25f};
GLfloat Vert[] = {0.0f, 0.8f, 0.0f, 0.25f};
GLfloat Bleu[] = {0.0f, 0.0f, 0.8f, 0.25f};
GLfloat Jaune[] = {0.8f, 0.8f, 0.0f, 0.25f};
GLfloat Rose[] = {0.8f, 0.0f, 0.8f, 0.25f};
GLfloat Cyan[] = {0.0f, 0.8f, 0.8f, 0.25f};
//on se contente de dessiner le cube,
//en utilisant cependant la fonction
//glColor4f() au lieu de glColor3f()
//car la composante alpha compte cette fois_ci
cube = glGenLists(1);
glNewList(cube, GL_COMPILE);
glBegin(GL_QUADS);
glColor4fv(Jaune);
glNormal3d(-1.0,0.0,0.0);
glVertex3d( -1, 1, 1);
glVertex3d( -1, 1, -1);
glVertex3d( -1, -1, -1);
glVertex3d( -1, -1, 1);
glColor4fv(Rose);
glNormal3d(0.0,1.0,0.0);
glVertex3d( -1, 1, 1);
glVertex3d( 1, 1, 1);
glVertex3d( 1, 1, -1);
glVertex3d( -1, 1, -1);
glColor4fv(Bleu);
glNormal3d(0.0,-1.0,0.0);
glVertex3d( -1, -1, 1);
glVertex3d( -1, -1, -1);
glVertex3d( 1, -1, -1);
glVertex3d( 1, -1, 1);
glColor4fv(Cyan);
glNormal3d(0.0,0.0,-1.0);
glVertex3d( 1, 1, -1);
glVertex3d( 1, -1, -1);
glVertex3d( -1, -1, -1);
glVertex3d( -1, 1, -1);
glColor4fv(Vert);
glNormal3d(1.0,0.0,0.0);
glVertex3d( 1, 1, 1);
glVertex3d( 1, -1, 1);
glVertex3d( 1, -1, -1);
glVertex3d( 1, 1, -1);
glColor4fv(Rouge);
glNormal3d(0.0,0.0,1.0);
glVertex3d(-1, 1, 1);
glVertex3d(-1, -1, 1);
glVertex3d( 1, -1, 1);
glVertex3d( 1, 1, 1);
glEnd();
glEndList();
}
La paramétrage principal est effectué par la fonction :
void glBlendFunc( GLenum sfactor, GLenum dfactor )
Si la fonction s’appelle « blend » (« mélanger » en anglais, ici en parlant des couleurs) et pas « transparency », c’est que la transparence n’est qu’une application de l’alpha-blending. C’est de loin la principale. Néanmoins, ce que fait réellement l’alpha-blending, c’est mélanger la couleur déjà affichée avec une nouvelle.
Le mélange est précisé par un appel à glBlendFunc, avec le premier paramètre indiquant par quelle valeur multiplier (canal par canal) la nouvelle couleur, le second la couleur déjà affichée. La nouvelle couleur affichée est la somme de ces deux multiplications. L’indice « s » indique que la nouvelle couleur est concernée, « d » qu’il s’agit de la couleur déjà affichée. La couleur affichée est : C = CsS + CdD. S et D étant paramétrés respectivement par sfactor et dfactor.
Principales valeurs de S en fonction de sfactor :
Valeur de sfactor |
Valeur de S |
ZERO |
(0,0,0,0) |
ONE |
(1,1,1,1) |
DST_COLOR |
(Rd,Gd,Bd,Ad) |
ONE_MINUS_DST_COLOR |
(1,1,1,1) - (Rd,Gd,Bd,Ad) |
SRC_ALPHA |
(As, As, As, As) |
ONE_MINUS_SRC_ALPHA |
(1,1,1,1) - (As,As,As,As) |
DST_ALPHA |
(Ad,Ad,Ad,Ad) |
ONE_MINUS_DST_ALPHA |
(1,1,1,1) - (Ad,Ad,Ad,Ad) |
SRC_ALPHA_SATURATE |
(f,f,f,1) avec f = min (As, 1 - Ad) |
Principales valeurs de D en fonction de dfactor :
Valeur de sfactor |
Valeur de D |
ZERO |
(0,0,0,0) |
ONE |
(1,1,1,1) |
SRC_COLOR |
(Rs,Gs,Bs,As) |
ONE_MINUS_SRC_COLOR |
(1,1,1,1) - (Rs,Gs,Bs,As) |
SRC_ALPHA |
(As, As, As, As) |
ONE_MINUS_SRC_ALPHA |
(1,1,1,1) - (As,As,As,As) |
DST_ALPHA |
(Ad, Ad, Ad, Ad) |
ONE_MINUS_DST_ALPHA |
(1,1,1,1) - (Ad,Ad,Ad,Ad) |
SRC_ALPHA_SATURATE |
(f,f,f,1) avec f = min (As, 1 - Ad) |
Les paramètres les plus courants sont
(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
Cela représente bien la transparence codée dans le canal Alpha :
la couleur affichée est multipliée par la valeur de transparence (si 0,
complètement transparent, si 1 opaque), et la couleur en dessous est multipliée
par le complément.
Le problème avec cette manière de rendre les objets transparents, c’est qu’il faut dessiner les surfaces dans l’ordre d’apparition pour avoir un meilleur rendu. en fait, ce qu'il faut faire, c'est dessiner la surface transparente juste après les surfaces que l'on doit voir au travers, et dessiner après les surfaces qui ne doivent pas apparaître. Par exemple, dans le programme final, j'ai placé une fenètre teintée en bleu. Comme je voulais que toute ma scène soit visible au travers, je la dessine presque en dernier (ce qu'il y a après est seulement ce qui n'apparaîtra jamais dedans).