L3IF Images
année 2004-2005
http://www710.univ-lyon1.fr/~jciehl/

TD6 - Lancer de Rayons

(Partie 1)


    L'objectif de ce TD est de construire un lancer de rayon minimaliste. La réalisation pratique sera vraisemblablement repartie sur plusieurs séances. Dans un premier temps, le lancer de rayon se limitera à déterminer les parties visibles de la scène (ray-casting). De même, afin de simplifier l'architecture et de limiter la taille du programe, nous ne nous interresserons qu'à quelques primitives élémentaires : sphère et triangle, par exemple.

    Plusieurs éléments doivent être mis en place :
  1. un repère global
  2. une caméra : un centre de projection et le type de projection (orthographiqe, perspective, etc.)
  3. une génération de rayons partant du centre de projection et passant par la surface d'un pixel du plan de projection
  4. des primitives géométriques : paramètres et fonction d'intersection par un rayon
  5. élimination des faces cachées
  6. éclairement

    Les parties suivantes détaillent chaque étape.



                        

Partie 1. Visualisation : repères, projection et génération de rayons

    La visualisation d'une scène peut se représenter de manière générale par l'algorithme suivant :
  1. positionner les objets dans un repère
  2. décrire la projection dans le même repère
  3. pour chaque pixel de l'image à calculer :
    1. déterminer l'objet visible à travers ce pixel
    2. déterminer la couleur de l'objet (et du pixel)
          pour déterminer quel objet est visible à travers un pixel :
déterminer la direction d'un rayon passant par le centre de projection et par le centre du pixel
déterminer l'objet dont l'intersection avec le rayon est la plus proche du centre de projection

    Le plus simple est de définir un repère local pour la caméra, c'est à dire que le centre de projection se trouve en (0, 0, 0) et que la direction de visée est (0, 0, -1) (même convention qu'openGL). Dans ce cas, la direction du rayon associé au pixel ( i, j ) d'une image de dimensions (N, M) est simplement :

        u( i )= Au + (Bu - Au) * i / (N -1)
        v( j )= Av + (Bv - Av) * j / (M -1)

    Les points A ( Au, Av, -s ) et B ( Bu, Bv, -s ) définissent le coin inférieur gauche (Au et Av sont négatifs) et le coin supérieur droit (Bu et Bv sont positifs) du plan de projection situé à la distance s du centre de projection. Le rayon R( i, j ) est donc définit par ( u( i ), v( j ), -s ).

    Une méthode simple pour définir une caméra dans un repère global consiste à calculer le repère UVW définit à partir d'un centre de projection (noté E), d'un vecteur de visé (noté G) et d'un vecteur indiquant une orientation (vers le haut, par convention) (noté Vup) :

    W= - G / || G ||
    U= Vup * W / || Vup * W ||
    V= W * U

    Le rayon R( i, j ) dans le repère UVW est  toujours : ( u( i ), v( j ), -s ). On peut aussi le décrire par : R( t )= E + t ( u( i ).U  + v( j ).V - s.W )

remarque :  * représente un produit vectoriel, et . un produit scalaire


Partie 2. Intersection rayon / primitive

    Pour chaque primitive que vous voulez utiliser, il faut fournir une méthode d'intersection prenant en paramètre un rayon (origine, direction) et déterminant l'existance d'une intersection avec la forme paramétrée du rayon. Cette methode devra également renvoyer le paramètre t correspondant à l'intersection ainsi que la normale à la primitive au point d'intersection (cf. élimination des parties cachées).

Partie 3. Intersection rayon / scène

    Une scène complète sera composée de plusieurs primitives, il y a de nombreuses manières d'organiser ces informations, la plus simple est certainement un tableau. Une solution interressante peut être de charger un ou plusieurs modèles maya .obj.

Partie 5. Elimination des parties cachées

    Il suffit de trier la distance des intersections calculées en parcourant la liste de primitives (la scène). L'objet visible est le plus proche du centre de projection.

Partie 6. Eclairement

    Dans un premier temps, on se contentera d'un éclairement local diffus, la couleur d'un point dépend de la normale à la surface, elle sera donc atténuée par le produit scalaire de la normale et de la direction désignant la source de lumière. Cette approximation correspond à une source de lumière directionnelle. Pour simuler une source de lumière ponctuelle, il suffit de connaître la position de la source et de calculer la direction entre le point de la surface et la source de lumière.

    Le calcul des ombres portées est relativement simple à ajouter dans ce cas, il suffit de déterminer si un objet intercepte le rayon émis par le point de la surface dans la direction de la source de lumière.


Réalisation

    Définissez les éléments nécessaires à un lancer de rayons minimal : une camera, un générateur de rayons pour la camera, une fonction d'intersection rayon / sphère ou rayon / polygone simple.

    squelette pour la camera

    libimg :
        lire / écrire des images TGA 24 + affichage simpliste openGL
        lire / écrire des images HDR (haute dynamique) + affichage et conversion simpliste vers TGA

    mob : charger et visualiser un modèle maya .obj

Question Subsidaire :

    Visualisez les primitives à l'aide d'openGL, choississez le point de vue et la direction de visée de manière interactive et calculez la visualisation de la scène. (indice : gluUnproject)