Ce procédé permet de définir et d'afficher des formes graphiques (des surfaces) qui ne sont pas intégralement opaques. Sans la transparence, les sprites ne pourraient pas avoir des formes quelconques et seraient tous des rectangles bariolés : il serait ainsi impossible de rendre le pourtour des sprites invisible, pour que l'on puisse voir le décor sous le sprite.
En 2D, la transparence ainsi gérée (par opposition avec la radiosité) est plus une commodité pour pouvoir regarder à l'intérieur d'objets qu'une simulation réaliste du processus physique, puisque par exemple la réfraction dans ces corps transparents en général n'est pas gérée, pas plus que la translucidité diffuse.
La transparence est très utile pour, entre autres, réaliser des effets spéciaux : lumière à travers fenêtres et vitraux, brouillards et fumées, épées magiques, fantômes, etc.
On distingue deux façons d'implémenter la transparence :
la couleur transparente (color key): conventionnellement, une certaine couleur n'est plus affichée du tout, laissant donc parfaitement voir à la place ce qu'il y a dessous.
Deux variantes existent : en mode paletté (chaque pixel est décrit comme un indice d'une palette commune à tout l'écran), un indice particulier correspond à la couleur qui n'est plus affichée, on l'appelle color key. En mode coordonnées de couleur (la couleur de chaque pixel est décrite individuellement comme un ensemble de coordonnées, ex : le triplet RGB), un certain point de cet espace colorimétrique est choisi comme étant complètement transparent. Ainsi, on peut dire que la couleur [R,G,B] = [ 120, 7, 32 ] ne doit plus être affichée du tout.
Un inconvénient connu de cette convention est que de nombreux traitements d'image (ex: l'anti-aliasing) ont tendance à légèrement modifier les couleurs de certains pixels. Il suffit qu'une coordonnée de couleur soit légèrement modifiée pour que, faute d'être strictement égale à la colorkey, les pixels la portant soient affichés, entraînant des artefacts graphiques indésirables
Ces deux types de transparence peuvent faire l'objet d'accélération matérielle. SDL peut ainsi tenter de maximiser les chances d'en bénéficier, par exemple quand on fournit les flags SDL_SRCCOLORKEY et SDL_SRCALPHA à SDL_CreateRGBSurface, en utilisant respectivement une couleur transparente ou un indice de transparence. SDL fera de son mieux pour créer la surface en question en mémoire système ou en mémoire vidéo, dans le but d'obtenir l'accélération matérielle (hardware blitting).
Quand une surface ne disposant pas de composante alpha doit être prise en compte par SDL comme une surface avec transparence, la composante alpha est considérée comme uniforme sur cette surface, et vaut 255 (surface complètement opaque).
Il est possible de transformer une surface ayant une couleur transparente en une surface ayant un indice de transparence, grâce à SDL_DisplayFormatAlpha qui convertit les pixels de la couleur transparente (color key) en pixels disposant d'une composante alpha, valant 0 (totalement transparents) pour les pixels qui étaient de la couleur transparente, et 255 (1, en composante alpha normalisée) pour les autres, qui gardent leur couleur. La valeur alpha intermédiaire 128 est souvent un cas particulier de transparence qui, appliqué sur toute une surface, fait l'objet d'optimisations entraînant un rendu spécialement rapide.
Enfin, l'encodage RLE (Run-Length Encoding), qui consiste à regrouper les pixels consécutifs de même couleur, peut significativement accélérer les transferts de mémoire (blittings) quand il s'applique à des sprites disposant de longues bandes horizontales de pixels transparents (i.e. de la même couleur que la color key).
Pour reprendre les conventions de SDL depuis la 1.1.5 ("complément à un" du degré d'opacité, qui auparavant était un degré de transparence), voici le sens de la coordonnées alpha : c'est le degré d'opacité d'un pixel, donc une coordonnée alpha de 0 (SDL_ALPHA_TRANSPARENT) signifie transparent et de 255 (SDL_ALPHA_OPAQUE) signifie opaque.
Pour expliquer plus facilement la suite, nous allons désormais considérer que la coordonnées alpha est normalisée entre 0 et 1, ce qui revient à diviser la quatrième coordonnée par 255. On peut alors aussi considérer que (1-a) mesure la transparence d'un pixel.
En pratique, supposons que sur une surface on ait un point P1.
r1 |
g1 |
b1 |
a1 |
r2 |
g2 |
b2 |
a2 |
La combinaison des deux donne un point P3 tel que :
r3 = a2.r2 + (1-a2).r1
b3 = a2.b2 + (1-a2).b1 g3 = a2.g2 + (1-a2).g1 |
Notons que ce résultat ne dépend pas de la transparence du point initial P1 (a1), car seule la transparence du point appliqué, P2, joue dans la superposition. Notons aussi que si P2 est complètement opaque (a2 normalisé vaut dans ce cas 1 selon les conventions SDL pour la transparence), P3 = P2 et ainsi P1 a complètement disparu sous P2.
Reste à savoir ce que vaut a3, question qui a un intérêt si l'on veut pouvoir appliquer le pixel résultant P3 sur un quelconque autre pixel.
a3 = 1 - (1-a1).(1-a2)
|
Cette valeur est celle qu'il serait logique d'obtenir,
mais par exemple l'utilisation de SDL_SetAlpha avec comme source et comme destination une
surface avec transparence, avec SDL_SRCALPHA de positionné, garde la
composante alpha de la surface de destination (a2) là où elle devrait
valoir, dans le cadre d'une vraie superposition, a3 = 1 -
(1-a1).(1-a2)
.
Ainsi, si P1 et P2 sont complètement transparents (a1=a2=0), P3 l'est aussi (a3=0). Si l'un des deux est transparent, seul le coefficient de l'autre importe.
Cette façon d'implémenter la transparence grâce à une quatrième coordonnée, le canal alpha, peut se faire au niveau le plus fin, le pixel, mais il est possible aussi de définir un unique degré de transparence pour une surface complète. Dans ce cas, il est possible de définir la valeur alpha commune à toute la surface grâce à la fonction SDL_SetAlpha, ce qui constitue aussi un moyen de désactiver la prise en compte de la transparence.
Dans le cas où une surface dispose de la transparence définie pixel par pixel et pour toute la surface, le codage par pixel supplante le codage global, qui n'est dès lors pas pris en compte (cf le pseudo-algorithme décrit dans SDL_BlitSurface, qui nous apprend entre autres qu'en l'absence d'une coordonnée alpha définie au niveau de chaque pixel, la color key et la valeur alpha de la surface éventuelles sont toutes les deux prises en compte lors d'un blitting).
Enfin, la composante alpha définie au niveau de la surface et non de chaque pixel peut être un moyen de faire des fondus-enchaînés ou des fondus au noir (effets de transition respectivement entre deux images ou une image vers l'écran noir) sans avoir à passer par la gestion de la correction gamma [Plus d'infos sur la correction gamma].
Pour charger des images disposant d'une composate alpha dans une surface, le plus commode est d'utiliser le format ouvert PNG (Portable Network Graphics), qui, outre une compression sans perte, gère la composante alpha, ce que ne fait pas le format propriétaire BMP. En revanche, seul le BMP est directement utilisable par SDL (SDL_LoadBMP), si bien qu'il peut être utile de recourir à SDL_image pour bénéficier des nombreux avantages du PNG.
Enfin, pour bénéficier de l'indice de transparence au niveau du pixel, il est généralement nécessaire de les coder en 32 bits (cf les formats de couleurs), une raison qui à elle seule fait préférer à certains développeurs ce mode riche de plus d'avantages que les 8, 16 ou 24 bits par pixel.
Si vous disposez d'informations plus détaillées ou plus récentes que celles présentées dans ce document, si vous avez remarqué des erreurs, oublis, ou points insuffisamment traités, envoyez-nous un courriel !