Projet Image - Rendu Non Photoréaliste

18 Juin 2004

Houlier Maxime - Imag 2A
Quillevere Ronan - Imag 2a

Introduction

Notre sujet consistait à coder un algorithme de rendu temps réel inspiré du principe des "lapped textures" présenté au SIGGRAPH 2000 (http://www.cs.princeton.edu/gfx/proj/lapped_tex/). Nous avons codé notre projet en c++ et nous avons utilisé les librairies suivantes :

  • Qt (http://www.trolltech.com)
  • QGLViewer (http://artis.imag.fr/Logiciels/QGLViewer/)
  • X3DToolkit (http://artis.imag.fr/Logiciels/X3D/)
  • OpenGl (http://www.opengl.org)

    Principe des "lapped textures"

    Il s'agit de texturer un objet 3d avec une texture appelée texture patch. On cherche à appliquer le texture patch un certain nombre de fois sur l'objet jusqu'à ce qu'il soit entièrement recouvert. Le problème initial est de définir un champ de vecteurs sur l'ensemble de l'objet (ou mesh) pour pouvoir définir l'orientation du patch au niveau de chaque face. Ensuite, on choisit une face aléatoirement sur le mesh, qui va servir de centre pour l'application du patch. L'application de le texture patch prend en compte le champ de vecteurs local aux faces recouvertes par celui-ci. On itère alors le procédé en choisissant une nouvelle face qui n'a pas été recouverte précédement, et cela jusqu'à ce que le mesh soit recouvert.

    Parcours du Mesh et création du "Surface Patch"

    Le Surface Patch est l'ensemble des faces qui sont recouvertes par un texture patch. Le premier algorithme développé durant le projet a été celui permettant de créer des surface patchs. Deux méthodes ont été implémentées, la première s'appuit sur un algorithme récursif qui agrandit le surface patch de proche en proche, la seconde est basée sur la distance à la face centrale du surface patch.

    Méthode 1 : Création du Patch de proche en proche

    Pour créer la patch nous utilisons une procédure récursive avec un paramètre de profondeur qui sert à limiter le nombre d'appels récursifs. Elle enregistre les faces déjà traitées pour l'expansion du surface patch courant, dans un vector. La procédure est appelée sur un face (origine) puis récupère celles qui l'entourent. Si les faces entourant l'origine n'ont pas encore été parcourues, on les stocke et l'on relance la procédure sur ces faces avec un paramètre de profondeur-1. Si elles ont déjà été parcourues, on ne lance pas l'appel récursif. La procédure s'arrète quand le paramètre de profondeur atteint 0.

    Méthode 2 : Création du Patch grâce à une norme

    Dans cette méthode, on crée un surface patch avec les faces dont la distance entre leur centre et le centre de l'origine est inférieure à une certaine valeur. Cette valeur est un multiple de la plus grande distance séparant le centre de l'origine et le centre d'une des ses faces directement voisine.

    Optimisation du Patch

    Le but est ici d'adapter au maximum le surface patch avec le texture patch. Nous avons codé un algorithme qui teste si un point appartient bien au polygone délimitant les bords du texture patch. Le principe est de calculer les intersections entre une droite passant par le point et le polygone de contrôle. Suivant la position des intersections on peut conclure à l'appartenance ou non du point.

    avant - après

       

    Application des coordonées de texture au Patch

    Méthode 1 : "Dépliage" du Patch

    Dans cette méthode le principe est de déplier les faces du patch dans le plan créé par la face d'origine du patch.

    L'inconvénient est qu'au moment de déplier les faces celles-ci peuvent se recouvrir. Cette méthode n'assure donc pas la continuité des coordonnées de textures entre les faces du patch. C'est pourquoi nous lui avons préféré la seconde méthode.

    Méthode 2 : Projection orthonormale

    Pour générer les coordonnées de textures des vertex du patch on réalise simplement une projection orthogonale selon z dans le repère 3D lié au centre de la face d'origine du patch. Pour cela il nous faut les coordonées des vertex dans le repère de cette face ce qui est obtenu par un changement de repère depuis le repère du mesh vers le repère de cette face.

    Cette méthode à l'avantage d'assurer la continuité des coordonnées de texture entre les faces d'un patch. Néanmoins si les déformations 3D du Patch sont importantes la texture et d'autant plus déformée. Il faut associer cette méthode à un contrôle de la déformation du Patch (voir plus loin).

    Améliorations

    Contrôle de la déformation

    Comme énoncé dans le paragraphe précédent il est important de vérifier que le Surface patch ne subit pas trop de déformations 3D. Sinon une fois la texture appliquée celle-ci va subir des déformations trop importantes pour obtenir un rendu de qualité. Cette problématique est d'autant plus importante avec des modèles comprenant beaucoup d'extrusion. Pour controler la déformation de l'objet on réalise un produit scalaire entre la face d'origine du patch et la face que l'on est en train d 'explorer. Si ce produit scalaire est inférieur à un seuil alpha alors on ne génére pas les coordonnées de textures de la face.

    avant - après

       

    Paramétrisation

    Pour l'instant, le surface patch était aligné sur le champ de vecteurs seulement au niveau de la face centrale. Pour améliorer la qualité du rendu, il est important que l'orientation de chaque face d'un surface patch soit alignée sur la direction du champ de vecteur au niveau de cette face et non simplement sur la face centrale. On va donc chercher à optimiser la paramétrisation des faces en s'appuyant sur des outils mathématiques. A partir du champ de vecteurs généré sur le mesh, on définit une base tangentielle (S,T) pour chaque face. Avec la paramétrisation choisie pour le calcul des coordonnées de texture pour la face centrale du surface patch, on définit une fonction linéaire permettant de passer du repère 3D du mesh au repère 2D de la texture. On va minimiser la différence, au niveau de chaque nouvelle face ajoutée lors de la création du surface patch, entre l'image de la base (T,S) locale à la face dans l'espace 2D des coordonnées de texture et la base de cette espace ,qui correspond à l'image de la base locale (T,S) de la face centrale du surface patch. La propriété utilisée est que l'on a: T= alpha*A+beta*B+gamma*C avec alpha+beta+gamma=0 et A,B,C les coordonnees 3D des points de la face considérée. Et donc, si on appelle phi la fonction de passage 3D vers 2D, on a par linéarité de phi: phi(T)= alpha*phi(A)+beta*phi(B)+gamma*phi(C) avec phi(X) les coordonnées de texture du point X, il en est de même pour S. On va minimiser phi(T)-(0,1) et phi(S)-(1,0) car pour la face centrale l'image de sa base est la base de l'espace 2D.

    avant - après

       

    Résultats

               

    Limitations de notre étude

    Multitexturing

    Les résultats que nous obtenons ne tirent pas partie des possibilités offertes par le multitexturing. En effet par manque de temps nous n'avons pas réussi à trouver une méthode efficace en terme d'aspect graphique pour le rendu. Le but était de mélanger les textures qui se superposent au niveau des bords du texture patch da façon à lisser cette superposition de textures. Mais ce "mélange des couleurs" est responsable d'un changement de teinte de la texture là où l'on utlise le multitexturing, car le problème est que l'on ne sait pas si l'on superpose la texture avec une partie transparente ou sans. Et les deux cas imposent des paramètres de blending différents.

    Calcul du champ

    Le manque de temps nous a empêchés d'implémenter le calcul d'un champ de vecteurs alignés sur la courbure de l'objet. Nous utilisons simplement un champ de vecteurs quelconque, que l'on a obtenu en effectuant le produit vectoriel entre le vecteur unitaire vertical et la normale de chaque face.

    Développements

    "Real-time hatching" : Voir projet de Alborini Bruno et Lemercier Mikael inspiré de http://www.cs.princeton.edu/gfx/proj/hatching/
    Fourure : http://www.research.microsoft.com/graphics/realtime_fur.asp