Rendu de terrain fractal en OpenGL
Alexandre Cruz, Julien Hognon, Jérôme Petazzoni
|Introduction
|Lamination géodésique
|Gestion du niveau de détail
|Mouvements de caméra
|Optimisation du rendu
|Conclusion
|
Introduction
But du projet ?
Nous avons décidé de nous appuyer sur un modèle
original : la lamination géodésique. Il s'agit d'une
transformation qui déforme une sphére (ou un ensemble
quelconque de points). En l'itérant assez longtemps, on
peut obtenir un sphéroïde pouvant passer pour une planète.
La planète étant modélisée par des triangles,
afin de bénéficier d'un rendu fin (mais gourmand) ou bien
grossier (mais rapide), nous partons d'une sphère comportant
un petit nombre de facettes. Nous avons implémenté un
système permettant d'affiner à volonté le rendu
(par création de triangles plus petits).
Lamination géodésique
La génération de terrain sphérique est une opération très simple.
Pour Chaque itération Faire
Déterminer alétoirement l'équation d'un plan passant à proximité du
centre de la sphère.
Pour Chaque point de la sphère Faire
Si le point est "devant" le plan Alors
Eloigner le point du centre de la sphère
Sinon
Rapprocher le point du centre
Fin Si
Fin Pour
Fin Pour
|
Nous pouvons voir que l'algorithme de base est trés intuitif et facile à implanter. Or, il n'est pas suffisant
d'en effectuer un implantation strict pour obtenir des résultats satisfaisant. Il faut en effet tenir compte d'un grand
nombre de paramètres comme le nombre d'itération, l'éloignement par rapport au centre, le pas
de déplacement des points, etc ...
Problèmes liés au mécanisme de lamination
Nous avons brièvement évoqué précédement le fait que le mécanisme de lamination, s'il
n'était pas controlé, pouvait donner de mauvais résultats.
Par exemple, étant donnée que la lamination consiste à éloigner ou rapprocher les point d'une
sphère par rapport au centre, on risque de dilater ou contracter la sphère de départ. Pour cela, on
ajoute une phase à la suite des laminations consistant à recalibrer la distance au centre de tous les points
grâce à une analyse statistique. Par ailleurs, on utilisera cette analyse pour déterminer les différentes
pages de couleurs appliquées au terrain.
D'autre part, il se peut que le relief soit beaucoup trop accidenté. Ceci est encore une fois une conséquence de
l'opérateur de lamination. En effet, d'un coté d'un plan, les points sont éloignés, de l'autre, ils
sont approchés, donc, on assiste à chaque itération à la création de "falaises locales". Ce
phénomêne est de plus accentué par le grand nombre de répétition du processus. Il faut donc, par
pur soucis esthétique, lisser le terrain en faisant une moyenne pondérée locale pour chaque point de la
sphère.
En bref, voici le résumé des opérations à éffectuer :
- Lamination
- Lissage
- Analyse statistique
- Recalibrage
- Attribution des couleurs
|
Résultats
Voici les différents résultats que l'on peut obtenir grâce à l'implantation de l'algorithme
décrit ci-dessus.
Gestion du niveau de détail
Nous avons quelques contraintes quant au modèle à utiliser pour le rendu :
- Il faut modéliser une sphère.
- Le modèle doit pouvoir être affiné à volonté (par ajout de sommets,
de faces...)
- On souhaite pouvoir intercaler des laminations et des affinements.
En effet, le temps d'une lamination est proportionnel au nombre de sommets,
il est donc préférable de les réaliser avec un petit nombre de sommets,
puis affiner le modèle afin d'obtenir un rendu plus fin. On peut
alors ajouter quelques laminations afin d'éviter d'obtenir un terrain
trop "lisse".
- Enfin, le modèle doit permettre de jouer en temps réel sur le niveau
de détail, afin d'obtenir soit une bonne qualité d'image, soit une
fluidité maximale.
Nous avons choisi de modéliser une sphère par un polyhèdre initial à
facettes triangulaires. Ensuite, lorsqu'on souhaite raffiner la
sphère, on subdivise chaque face en quatre triangles plus petits.
Cette opération peut être réalisée autant de fois qu'on le désire.
Lors de l'insertion de nouveaux sommets (au milieu de chaque segment),
ceux-ci sont interpolés par rapport aux extrémités du segment.
Le nouveau sommet est placé exactement au milieu du segment, puis
il est multiplié par un coefficient calculé de façon à ce que sa
distance au centre de la sphère soit la moyenne des distances des
deux extrémités (dans la figure ci-dessous, $P'$ est le milieu de $MN$,
et on place $P$ de façon à ce que $OP$ soit la moyenne de $OM$ et $ON$).
La structure de données utilisée conserve la relation d'arborescence
existant entre une grande face et les quatre faces plus petites qui la
composent. Cette propriété sera utilisée pour l'optimisation de l'affichage
(voir plus bas).
Un petit exemple (le nombre de faces affiché est le nombre de faces
réellement envoyées à OpenGL - voir plus bas) :
Mouvements de caméra
Les différentes opérations applicables à une caméra sont les suivantes :
- look around : la caméra ne se déplace pas et regarde dans toutes les directions
- dolly : la caméra se déplace d'avant en arrière
- pan : la caméra latéralement et en hauteur
- turn around : la caméra tourne autour de sa cible
- changement de zoom
- changement de focale
Afin de pouvoir effectuer ces opérations, il a fallut utiliser une structure spécifique
permettant de placer et d'orienter la caméra dans l'espace. Une caméra a donc été
définie à l'aide des champs suivants :
- eye : position de la caméra
- target : position du point visé par la caméra
- dir : vecteur représentant la direction dans laquelle la caméra est orientée
- up : vecteur
- fov : distance focale de la caméra

Note : le vecteur "right" que l'on peut voir sur la figure est utile mais il n'a pas besoin d'être stocké
car il peut être retrouvé à l'aide du produit vectoriel de "dir" et "up".
Les différents mouvements de caméra sont donc définis en appliquant des rotations ou des translations
aux vecteurs et points représentant une caméra.
exemple : dans le cas du look around, on effectue une rotation des vecteurs "dir" et "up" ainsi que du point
"target" autour du point "eye".
Note : toutes ces opérations sont définies à l'aide de matrices de rotation et de translation
Optimisation du rendu
Nous avons apporté une attention toute particulière à la vitesse
d'exécution de notre programme. Voici donc les facteurs limitants
(bottlenecks) que nous avons identifiés, et les réponses apportées
à chacun des problèmes :
- Mémoire réquise pour le stockage des sommets et des faces.
- Utilisation de float au lieu de double pour le stockage
des coordonées.
- Stockage des normales et des couleurs aux sommets, mais pas
aux faces.
- Un grand nombre de faces cachées ou hors de l'écran sont envoyées
inutilement au moteur de rendu OpenGL.
- Les faces cachées ne sont pas envoyées à OpenGL (on détermine à
partir des normales aux sommets et de la caméra si une facette triangulaire
fait face à la caméra ou pas).
- Lors du raffinement du niveau de détail de la sphère, on conserve
en mémoire toutes les informations concernant les niveaux précédents. À
tout instant, on dispose donc d'une sphère aussi fine ou aussi grossère
qu'on le désire. En fonction de la distance à la caméra, on peut donc
réduire le nombre de faces affichées.
- Toujours lors du raffinement de la sphère, on stocke pour
chaque facette la référence de la facette plus grande dont elle est issue,
et inversement, lorsqu'une face est divisée en quatre, on conserve les
références de ses "filles". Ainsi, au lieu d'examiner toutes les
petites facettes pour les envoyer à OpenGL, on examine une grande facette :
si elle est totalement visible, on affiche inconditionnellement toutes
ses filles ; si elle est totalement cachée, on ne poursuit pas la
récursion ; enfin, si elle est partiellement visible, on examine ses
quatre filles.
Enfin, nous avons utilisé diverses techniques OpenGL suggérées
par le Red Book ; par exemple les tableaux de sommets, de
normales et de couleurs (chaque sommet appartient à six
triangles ; au lieu de l'envoyer six fois, on l'envoie
la première fois, puis on le référence par son indice).
Conclusion
(parler ici de la re-invention de la roue?)