Mandragor


Le tri des faces et le Z-Buffer

Jusqu’à présent, le point 7 pourrait faire rire toute personne qui a déjà programmé un moteur 3D, car c’est en général par là qu’on commence (l’important n’est-il pas d’avoir quelque chose de joli à l’écran ?) et c’est également par là qu’on termine quand on se rend compte que ça n’est pas si simple que ça.

Outre le fait qu’afficher un triangle, avec une texture, des couleurs et même parfois de la transparence n’est pas quelque chose de facile en soit, il faut encore savoir dans quel ordre les afficher, les faces.

Ben wais, imaginez que vous ayez un tore. C’est joli un tore, non ? Pour ceux qui ne voient pas, un tore c’est un anneau, finalement... Bon, on veut dessiner notre tore. On fait donc un peu de backface culling, ce qui supprime toutes les faces qui nous tournent le dos.

Wé mais bon, il y a toute une série de faces qui passent à travers le test du backface culling sans pour autant être visibles, vu du haut ça donne :

En rouge, j’ai mis les parties qui sont éliminées par le clipping.

En bleu, on a ce que le backface culling a supprimé.

Finalement restent en vert vers parties « visibles » du tore. Visibles, vraiment ? Moi j’ai comme l’impression qu’on ne va pourtant voir que la partie la plus proche, qui recouvre la partie intérieure, plus éloignée.

Hé oui, mauvaise nouvelle, si le backface culling élimine une bonne moitié des faces non visibles, elle ne les élimine pas toutes non plus... (ce qui revient à dire qu’en moyenne dans un objet, beaucoup moins de la moitié des faces ne sont réellement visibles, ça laisse songeur et ça permet de trouver la motivation pour des systèmes encore plus performants, comme pour les moteurs de Quake etc...)

Et donc, si on ne fait pas attention, on va tout d’abord afficher les faces qui sont tout devant, pour ensuite afficher les faces qui sont les plus éloignées (pourquoi pas, après tout, hein ?), et le résultat va être assez moche. Ce qu’il faut donc faire avec les faces qui restent, c’est les trier selon leur distance à l’observateur (ou selon leur coordonée Z, ce qui ne revient pas exactement au même mais qui suffit malgré tout, ça évite de calculer une distance), et commencer à afficher d’abord les faces les plus éloignées, pour poursuivre et terminer avec les faces les plus proches.

L’ennui, c’est que si des faces, il y en a beaucoup, trier ça va prendre un sacré temps (et puis c’est fatigant). Remarquez, des algorithmes de tri, il y en a de très performants (je pense bien sur au quicksort en nlog(n) pour les amateurs), mais c’est pas la panacée non plus (quoique parfois on ne peut pas s’en passer, pour la transparence par exemple).

D’autant plus que le tri ne permet pas de régler le problème suivant, vu de l’avant :

Quel que soit l’ordre dans lequel vous allez afficher ces quatre rectangles, je vous assure que le résultat ne sera pas bon. D’ailleurs, moi dans Word (NB de Freedoomer qui se fait chier à passer tout ca en HTML: bah désolé tout le monde c\'est plus en Word =)), j’ai eu du mal à dessiner cette fichue figure vu que ça fonctionne par un système de plan, et donc également de tri en Z, finalement. Regardez les bricolages que j’ai du faire si vous dissociez ce truc (bon je suis pas très doué non plus, hein ? =))

Bon, vous me direz que ce genre de dessins, on ne le rencontre pas souvent et vous aurez raison, mais c’est juste un exemple, des situations qui font foirer le tri en Z, il y en a plus que vous ne le pensez. Sans compter qu’un tri ne vous permettra jamais de gérer l’intersection de deux triangles...

Il faut donc autre chose, et c’est autre chose, c’est le Z-Buffer.

L’idée est assez simple. Si, au moment de tracer le triangle à l’écran, on connaît la position en Z de l’espace caméra de chaque sommet (ce qui est le cas, on en a eu besoin pour le clipping et d’ailleurs pour le tri si on fait du tri), on peut connaître, monayant quelques petits calculs savants qu’on appelle une règle de trois (sisi) ou plus précis quand on fait de la correction de perspective (voir plus loin, toujours plus loin...) la position en Z de chaque points du triangle sur l’écran.

A quoi ça sert ? Et bien c’est évident, on garde, dans un buffer (d’où le nom, subtil), la position Z de chaque point dessiné sur l’écran (ou une valeur « très loin » si aucun point n’est dessiné à cet endroit sur l’écran). Ca demande un peu de place en mémoire, comme en général on stocke les valeurs sur 32bits et que les écrans sont en 1024x768, ça prend quelque chose comme 4mo pour ce z-buffer. Mais bon, il faut ce qu’il faut.

Et on en fait quoi de ce buffer ? C’est simple voyons, avant de tracer un pixel sur l’écran, on regarde si la position Z (la distance, finalement) du point que l’on va dessiner est plus éloignée que celle du pixel déjà dessiné à cet endroit. Si c’est le cas, alors on ne dessine rien du tout et on passe au pixel suivant. Sinon, et bien on trace le pixel et on mes à jour le Z-Buffer.

Grâce à ce système, non seulement on a plus besoin de faire attention à l’ordre d’affichage de nos faces (plus de tri), mais en plus on peut gérer les situations comiques vues un peu plus haut, et, comble du rafinement, on peut gérer au pixel près les intersection de faces de deux objets qui se rentrent dedans. Que demander de plus ?