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 :

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 ?

pas correct... correct

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.