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 :
- un repère global
- une caméra : un centre de projection et le type de projection
(orthographiqe, perspective, etc.)
- une génération de rayons partant du centre de projection
et passant par la surface d'un pixel du plan de projection
- des primitives géométriques : paramètres
et fonction d'intersection par un rayon
- élimination des faces cachées
- é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 :
- positionner les objets dans un repère
- décrire la projection dans le même repère
- pour chaque pixel de l'image à calculer :
- déterminer l'objet visible à travers ce pixel
- 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)