M2 - Images
TP 1 - Méthodes de monte carlo
et lancer de rayons.
L'objectif de ce tp est de mettre en place les éléments nécessaires
pour une simulation "correcte" de l'éclairage direct et indirect
basé sur les méthodes de Monte Carlo.
Utilisez les scenes de test suivantes, elles sont composées de très
peu de geométrie (triangles), ce qui permet d'éviter de construire
une structure accélératrice pour limiter les calculs de visibilité
(au moins dans un premier temps ...) :
Installez la mise à jour de gKit2
pour ce tp.
Utilisez ray_tutorial1.cpp (inclut dans l'archive) comme point de
depart.
mise à jour de gKit2 13/12:
nettoyage des projets.
mise à jour de gKit2 20/12: image_viewer, correction
du bug de lecture des matières.
Partie 1 : lancer de rayons et visibilité
exercice 1 : visualisation par lancer de rayons
Pour chaque pixel de l'image résultat, déterminez les coordonnées de
l'origine du rayon dans le repère de la scène, ainsi que celles de
son extrémité.
Dans quel espace est-il le plus simple de calculer l'origine et
l'extrémité du rayon ?
Calculez l'intersection du rayon avec tous les triangles de la scène
(utilisez gk::MeshIO::read( )
pour la charger) et ne
conservez que l'intersection valide la plus proche de l'origine du
rayon.
remarques :
gk::Ray
permet de représenter et de manipuler
facilement un rayon.
gk::Hit
permet de représenter simplement une
intersection,
- les fonctions d'intersections rayon / triangle et rayon / bbox
sont déjà écrites :
gk::RTTriangle::intersect( )
et gk::BBox::intersect( )
.
indications : votre
programme devrait ressembler à :
main
creer une image
charger un ou plusieurs objets
pour chaque pixel de l'image :
générer un rayon dans le
repere de la scene
// trouver le point visible
pour le rayon
pour chaque triangle de chaque
objet :
transformer
le rayon dans le repere local de l'objet
calculer
l'intersection du rayon avec le triangle,
conserver
l'intersection si elle est valide et plus proche que la dernière
trouvée
si une intersection valide
existe
ecrire un
pixel blanc dans l'image
sauver l'image
il est également plus lisible d'écrire les calculs d'intersection
dans une fonction séparée :
bool intersection( const gk::Ray& ray,
const gk::Mesh *mesh, gk::Hit& hit );
qui renvoie vrai ou faux, selon le cas, et
complète la structure gk::Hit
en cas d'intersection.
remarque : pour déterminer la position du point
d'intersection à l'abscisse t, le plus simple est d'utiliser
l'opérateur ( ) de gk::Ray. par exemple, gk::Point p=
ray(hit.t);
exercice 2 : matière
Choisissez une couleur arbitraire pour chaque triangle de la scène.
Utilisez cette couleur pour construire l'image des objets visibles.
exercice 3 : ombres et éclairage direct
Choisissez un point sur la source de lumière et vérifiez que chaque
point visible par la caméra est également visible par la source de
lumière.
Comment déterminer l'origine et la direction du rayon permettant de
faire ce test ?
Les points non éclairés seront noirs.
exercice 4 : sources étendues
Générez plusieurs points à la surface des sources de lumières. cf
gk::Triangle::sampleUniform(). Comment déterminer la couleur du
pixel ?
voila un exemple de ce que l'on peut obtenir. remarque : l'image de
gauche est incorrecte. pourquoi ?
exercice 5 : matières
Utilisez la description de matières associée aux triangles pour
calculer l'image.
remarque : les matières sont décrites dans un fichier
texte, "materials.mtl", il est très simple de le modifier.
Par exemple, la matière par défaut s'appelle "diffuse50SG", elle
est déclarée :
newmtl diffuse50SG
Kd 0.7 0.7 0.7
ce qui correspond à une matière diffuse grise qui réflechit 70%
de la lumière incidente. La couleur décrite par Kd dans le fichier
mtl est conservée dans le champ diffuse_color de la structure
gk::MeshMaterial.
pour utiliser une texture pour moduler le résultat, il suffit
d'ajouter la ligne map_Kd nom_image, par exemple :
newmtl diffuse50SG
Kd 0.7 0.7 0.7
map_Kd simple.png
Voici les correspondances entre le fichier mtl et les valeurs
stockées dans un objet gk::MeshMaterial :
Kd r g b
|
MeshMaterial::diffuse_color=
Normalize(r,g,b)
MeshMaterial::kd= Length(r,g,b)
|
map_Kd image
|
MeshMaterial::diffuse_texture= image
|
Ks r g b
|
MeshMaterial::specular_color=
Normalize(r,g,b)
MeshMaterial::ks= Length(r,g,b)
|
map_Ks image
|
MeshMaterial::specular_texture= image
|
Ns |
MeshMaterial::ns= Ns
|
Avec les valeurs de l'exemple précédent :
gk::MeshMaterial material;
material.name= "diffuse50SG"
material.kd= 0.7;
material.diffuse= gk::Energy(1.0, 1.0, 1.0);
material.map_Kd= "simple.png"
exercice 6 : toutes les sources
Comment répartir N points à la surface de l'ensemble des sources
de lumières (au lieu de N par source, solution a priori utilisee à
l'exercice 4) ?
L'idée est de choisir aléatoirement d'abord une source, puis un
point sur cette source, et de recommencer N fois.
Proposez au moins 2 manières différentes de choisir une source
parmis l'ensemble de sources.
Vous pouvez tester vos idées avec la scène emission.obj, prévue
pour ce cas précis.
Quel comportement observez-vous dans chaque cas ?
exercice 7 : éclairage indirect
En plus de calculer la lumière directement incidente, calculez aussi
la lumière réfléchie indirectement par les autres objets de la
scène.
L'idée est d'estimer la lumière directe avec 1 seul point choisit
sur l'ensemble des sources et d'estimer la lumière indirecte en
choisissant une autre direction. Il suffit alors de trouver l'objet
visible dans cette direction et d'estimer l'energie directe qu'il
réfléchit.
Comment choisir cette nouvelle direction pour estimer la lumière
indirecte ?
Vous pouvez tester vos idées avec les scènes geometrie.obj et
secondary.obj.
Quel comportement observez-vous ? Essayez plusieurs choix de
directions pour estimer la lumière indirecte.