Top Banner
ENSSAT Imagerie numérique IMR.2 Synthèse d'images TP n°1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé, car le but est de comprendre certains mécanismes qu'on retrouve dans les programmes OpenGL. Plusieurs concepts sont employés sans être définis, comme les éclairements de Lambert et de Phong. Ils seront pleinement justifiés dans la suite du cours. Ici, on va seulement constater leur justesse expérimentalement. Le point de départ est un logiciel inachevé écrit en Java. Il est à télécharger sur la page Moodle du cours. La version C++ a été enlevée étant ni portable, ni plus efficace. Note : le projet Java est destiné à Java8 et l’environnement JavaSE1.7. Il est préférable de travailler avec Eclipse, dans une version récente. Sinon, il est possible que Java8 ne soit pas l’environnement proposé par défaut sur votre machine. Il faut alors le supprimer puis le ré-ajouter, et accepter les corrections automatiques allant dans ce sens. Dans Eclipse, il faut créer un nouveau projet. Il doit séparer les sources et binaires, dossiers src et bin. Une fois le projet créé, décompresser l’archive et remplacer les dossiers du projet par ceux de l’archive, src, libs et scenes. Ensuite, il faut ajouter junit4 et libs/ini4j dans le classpath du projet. L’archive contient un fichier .classpath qui fait cela. Pour l’exécution, il faut créer une configuration de lancement pour démarrer sur la classe Main et avec un paramètre qui doit être "scenes/scene1.ini". Ce logiciel est à compléter tout au long de ce TP, avec les indications de cet énoncé. Prenez d’abord le temps de regarder sa structure : Tuple, Vecteur, Point, Couleur : pour les calculs mathématiques, Objet3D, Sphere, Lampe, Scene : pour représenter les éléments à dessiner, Constantes, Rayon, Lancer : pour l'algorithme de dessin, Makefile permettant de compiler et lancer en ligne de commande, mais avec Eclipse, il n’est pas nécessaire. Le logiciel fourni contient des tests unitaires dans la classe Tests (à lancer avec le runner de junit4). Ce n'est pas parfait, cela signale seulement des erreurs très grossières et évite de galérer ultérieurement. 1 11/09/2020
18

TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Sep 27, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

ENSSAT Imagerie numériqueIMR.2 Synthèse d'images

TP n°1 : lancer de rayonsLe but du TP est de concevoir complètement un programme de synthèse d'images parlancer de rayons. Ce programme ne sera pas optimisé, car le but est de comprendrecertains mécanismes qu'on retrouve dans les programmes OpenGL. Plusieurs conceptssont employés sans être définis, comme les éclairements de Lambert et de Phong. Ilsseront pleinement justifiés dans la suite du cours. Ici, on va seulement constater leurjustesse expérimentalement.

Le point de départ est un logiciel inachevé écrit en Java. Il est à télécharger sur la pageMoodle du cours. La version C++ a été enlevée étant ni portable, ni plus efficace.

Note : le projet Java est destiné à Java8 et l’environnement JavaSE1.7. Il est préférable detravailler avec Eclipse, dans une version récente. Sinon, il est possible que Java8 ne soitpas l’environnement proposé par défaut sur votre machine. Il faut alors le supprimer puisle ré-ajouter, et accepter les corrections automatiques allant dans ce sens.

Dans Eclipse, il faut créer un nouveau projet. Il doit séparer les sources et binaires,dossiers src et bin. Une fois le projet créé, décompresser l’archive et remplacer lesdossiers du projet par ceux de l’archive, src, libs et scenes. Ensuite, il faut ajouterjunit4 et libs/ini4j dans le classpath du projet. L’archive contient un fichier.classpath qui fait cela.

Pour l’exécution, il faut créer une configuration de lancement pour démarrer sur la classeMain et avec un paramètre qui doit être "scenes/scene1.ini".

Ce logiciel est à compléter tout au long de ce TP, avec les indications de cet énoncé.Prenez d’abord le temps de regarder sa structure :

• Tuple, Vecteur, Point, Couleur : pour les calculs mathématiques,

• Objet3D, Sphere, Lampe, Scene : pour représenter les éléments à dessiner,

• Constantes, Rayon, Lancer : pour l'algorithme de dessin,

• Makefile permettant de compiler et lancer en ligne de commande, mais avecEclipse, il n’est pas nécessaire.

Le logiciel fourni contient des tests unitaires dans la classe Tests (à lancer avec lerunner de junit4). Ce n'est pas parfait, cela signale seulement des erreurs très grossièreset évite de galérer ultérieurement.

1 11/09/2020

Page 2: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Points et vecteursPour commencer, il faut terminer une petite bibliothèque de classes et méthodes pour lescalculs géométriques.

La classe Tuple représente un triplet de coordonnées x,y,z. Cette classe est dérivée pourreprésenter des Point et des Vecteur ayant des méthodes spécifiques. Ce n’est pas lecas, mais on pourrait en faire une variante pour représenter les Couleur — de fait, lescouleurs sont une classe spécifique car leurs composantes s’appellent r,v,b.

Dans ces classes, les méthodes de classe et d’instance créent de nouvelles instances, ex  :Vecteur.add(u,v) et u.add(v) retournent un nouveau vecteur somme de u et de v.On aurait pu faire en sorte que ces méthodes modifient le vecteur u ; ça aurait réduit lenombre d’allocations mémoire.

- Compléter le constructeur de la classe Vecteur qui reçoit deux Point en paramètres.

- Compléter les méthodes sub présentes dans les classes Point et Vecteur.

- Compléter la méthode qui calcule le produit scalaire entre deux Vecteurs. Elle s'appelledot. Réveillez vos souvenirs du lycée : quel lien y-a-t-il entre le produit scalaire et lanorme d'un vecteur ? Quel est le rapport entre le produit scalaire de deux vecteurs etl'angle qui existe entre eux ?

- Compléter la méthode norme2 de la classe Vecteur qui retourne le carré de la normed’un vecteur. Cette méthode est utilisée pour normaliser un vecteur, c’est à dire mettresa « longueur » à 1 sans changer sa « direction ». Il y a deux méthodes pour normaliser.

Représentation des rayonsSoit une classe Rayon représentant une demi-droite 3D, elle contient les variablesd'instance P (point de départ de la demi-droite) et V (vecteur directeur, normé), ainsi qued’autres variables qui seront décrites ultérieurement.

- Écrire le constructeur Rayon(Point p1, Point p2) auquel on fournit deux points :p1 est le point de départ du rayon et son vecteur directeur va de p1 à p2. Il fautnormaliser ce vecteur.

- Il y a un autre constructeur qui prend directement un point et un vecteur. Le vecteurest à normaliser (sauf si on considère qu'il l'est toujours, mais il faudrait voir ce qu’il enest à chacun des appels).

Écran, œil et projection : classes Rayon et CameraOn s’intéresse aux calculs géométriques pour construire un Rayon partant de l’œil ettraversant un pixel. Il y a deux repères en compétition : le repère 3D correspondant auxobjets et lampes à dessiner et le repère de l’écran. On veut pouvoir positionner la scènecomme on veut, mais cependant pas faire trop compliqué, donc on choisit de n’avoirqu’un seul repère, celui du plan de l’écran, l’œil étant derrière et la scène devant.

Soit un Point appelé Œil, situé à une distance D de l'écran et centré par rapport à cetécran. La taille de l'écran est (Largeur, Hauteur) et le pixel de coordonnées écran(xe=0,ye=0) est situé en haut et à gauche.

2 11/09/2020

Page 3: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Quelles sont les coordonnées 3D du Point Œil ? Soit un pixel ayant comme coordonnéesécran Pe(xe,ye). Ce pixel correspond à un Point 3D P(x, y, 0) qui est à calculer, c’est àdire quelle est la relation entre (x,y) et (xe,ye) ? Vos équations doivent tenir compte dufait que les pixels doivent rester carrés malgré la différence entre largeur et hauteur.

- Écrire les formules de calcul du rayon entre l’œil et Pe. Elles sont à placer dans laméthode getRayon de la classe Camera.

En pratique, il faut prendre en compte un coefficient supplémentaire : un facteurd'agrandissement entre les deux systèmes de coordonnées. Il faudra diviser x et y par laconstante echelle dépendant de la taille de la fenêtre et d'un « champ de vision ».

Intersection de rayons et de sphères : classe SphereLa classe Sphere représente une sphère, ses membres sont un Point appelé centre etun réel rayon1. C’est une sous-classe de Objet3D.

- Écrire la méthode getIntersectionDistance qui renvoie la distance de la plusproche intersection entre cette sphère et le point de départ du rayon. NB : on neconsidère qu’une seule sphère pour l’instant. La méthode ne doit pas retourner devaleurs négative qui signifieraient un contact dans le dos de la demi-droite. La méthoderenvoie la distance + s'il n'y a pas d'intersection. Voir le schéma suivant, le rayontouche la sphère rouge en deux points, et on renvoie la distance du plus proche des deux.

NB : le rayon est dessiné partant de l’œil, mais en fait, il part du pixel.

1 attention, le mot rayon a deux sens dans cet énoncé : rayon de la sphère (demi-diamètre, radius enanglais) et rayon lumineux (demi-droite, ray en anglais).

3 11/09/2020

dist

Page 4: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Normalement à ce stade, tous les tests unitaires doivent réussir.

Scène de sphères : classes Scene et RayonLa scène est une liste d’ Objet3D qui sont tous des sphères. Voir la classe Scene.

Pour dessiner la scène, il va falloir chercher les intersections d'un Rayon avec tous lesobjets de cette scène. Plusieurs objets peuvent être coupés par le rayon, mais seul le plusproche nous intéresse car c'est lui seul qui est visible et qui donne la couleur au pixel.

Pour représenter le point le plus proche de l'écran et l'exploiter utilement ensuite, onrajoute trois variables d'instance dans la classe Rayon : Objet3D objet; floatdistance; Point contact; qui décrivent précisément le point de contact : objetvaut null s'il n'y a aucun contact entre ce rayon et les objets de la scène, sinon c'est leplus proche objet rencontré par le rayon, et dans ce cas, distance donne la distance ducontact et contact donne les coordonnées du point.

- Lorsqu’une intersection est trouvée, on calcule les coordonnées du point de contact.C’est le rôle de la méthode calcContact() de la classe Rayon. Programmer cetteméthode, sachant qu’elle se base sur distance, ainsi que P et V pour calculer contact.

- Écrire la méthode de la classe Scene : bool getClosestIntersection(Rayonincident, Sphere sauflui) qui parcourt la scène à la recherche de l'objet le plusproche traversé par le rayon, sauf l'objet indiqué dans le paramètre, ceci pour ne pastrouver des intersections des rayons émis par les objets avec eux-mêmes à cause desimprécisions de calcul. Cette méthode renvoie true s'il y a au moins une intersection,dans ce cas elle affecte aussi les membres d’instance du rayon : objet, distance etcontact, ce dernier étant calculé avec incident.calcContact().

Algorithme général : classe MainSoit une image de taille (Largeur, Hauteur) à dessiner en lancer de rayons. Admettonsque, dans la classe Objet3D (la superclasse de Sphere), on dispose déjà de la méthodeCouleur getColor(…, Rayon rayonincident, …); qui calcule la couleur d'unrayon traversant une sphère. Elle sera à programmer ultérieurement, car elle est assezcomplexe.

La classe Main fournit la méthode drawPixel(Couleur coul, int xe, int ye);qui dessine un pixel de cette couleur. Cette méthode est appelée par la méthodeTracerImage qui est déjà programmée car elle est emmêlée avec l’affichage d’une jauged’avancement sur l’interface graphique, et également l’affichage rapide d’un brouillond’image.

- Étudier l’algorithme de la méthode TracerImage. Son cœur est une double boucle surtous les pixels. Sur chacun, elle appelle la méthode getCouleurPixel(xe, ye, …).Celle-ci est à programmer. Enfin, la méthode dessine le pixel de cette couleur.

- Programmer la méthode getCouleurPixel. Elle crée un rayon partant de l'œil,passant par le pixel à dessiner, calcule et retourne la couleur de ce rayon. La couleur estcalculée avec la méthode getColor de la classe Objet3D. À noter que celle qui vous estfournie ne fait que retourner du jaune vif. S’il n’y a pas d’intersection avec un objet, alorsil faut retourner la couleur du ciel, calculée avec la méthode getSkyColor de la classeRayon.

Bilan intermédiaireÀ ce stade, voici la succession simplifiée des appels des méthodes :

4 11/09/2020

Page 5: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Dans Main.java :

1) entrée dans la méthode main()

2) chargement de la scène : scene = new Scene(nom du fichier à lire, c’est le premierparamètre fourni au lancement);

3) affichage d’une fenêtre à l’écran associée à un SwingWorker (thread de dessin)

4) ce thread appelle la méthode doTracerImage(largeur, hauteur) : double boucleen xe, ye pour colorer chaque pixel à l’aide de getCouleurPixel(xe, ye) :

a) construction d’un rayon œil → pixel(xe,ye transformés en x,y,z) appelé initial

b) appel à la méthode Scene.getClosestIntersection(initial)

i. appels à la méthode Sphere.getIntersectionDistance(initial)

ii. appel à la méthode Rayon.calcContact() sur la sphère la plus prochepour finaliser les coordonnées du point de contact

c) à ce stade, si le rayon initial frappe une sphère, alors cette sphère avec ladistance et les coordonnées du point de contact sont présents dans le rayon

d) appel à la méthode Objet3D.getColor(scene, initial) ou sinoninitial.getSkyColor()

Deux méthodes importantes dans la classe Objet3D et sa sous-classe Sphere :

1) La méthode getIntersectionDistance(Rayon incident) calcule la distanced’intersection entre l’objet et le rayon incident, retourne +∞ si aucun. Elle stockeaussi cette distance dans le rayon.

2) La méthode getColor(scene, incident) retourne la couleur de l’objet au pointd’intersection trouvé. À ce stade, la couleur est constante, jaune vif, mais devraappliquer un modèle d’éclairement réaliste au cours de ce TP. Il faudra utilisertoutes les informations : point de contact, géométrie de la sphère, lampes, etc.

Éclairement diffus : classes Objet3D et LampeOn va maintenant écrire la méthode getColor de la classe Objet3D. Elle reçoit unRayon en paramètre et calcule la couleur qu'il voit.

Soit une lumière positionnelle ponctuelle représentée par un Point position et uneCouleur. Soit un rayon (P,V) dessiné en pointillés qui arrive sur la sphère au point« Contact ». On veut la teinte de ce point pour pouvoir le dessiner à l'écran. L'équationde Lambert donne la teinte (shade en anglais) en fonction du vecteur normal N, de la

5 11/09/2020

Page 6: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

direction de la lumière L, de sa couleur et intensité KL et des caractéristiques dumatériau Kd :

Couleurdiffuse = cos(α) * Kd * KL = (N.L) * Kd * KL

Note 1 : Tous les vecteurs concernés doivent être normalisés.

Note 2 : Ce calcul est à faire seulement si le produit scalaire N.L est positif.

Cette équation modélise l'éclairement d'une surface parfaitement mate. Nous verronsdans la partie 4 du cours comment d'autres matériaux sont modélisés.

Questions :

• Comment calculer les coordonnées du vecteur normal N au point de contact ?

• Comment calculer les coordonnées du vecteur L ?

• Comment les ombres apparaissent-elles dans le dos des objets éclairés ?

• Comment fait-on s'il y a plusieurs sources de lumière ?

- Programmer le calcul de l’éclairement diffus dans la méthode Objet3D.getColor. Laliste des lampes est à demander à l’instance de scene passée en paramètre.

À ce stade, chaque sphère doit avoir une couleur spécifique et plus ou moins claire enfonction de la lumière. Il n’y a pas d’ombres portées, seulement une ombre dans le dosdes objets par rapport aux lampes.

Éclairement spéculaireL'éclairement spéculaire provient d'un reflet de la lumière sur la surface quand celle-ciest suffisamment lisse. La formule de Phong donne la teinte en fonction de la couleur deréflexion du matériau Ks et de la couleur de la lampe KL :

Couleurspéculaire = (R.-V)ns * Ks * KL

Le vecteur -V est l'opposé du vecteur directeur du rayon, c’est un vecteur qui désignel'œil. Le vecteur R est le miroir du vecteur L par rapport à N, c’est le vecteur qui indiquelà où partent les reflets, et ns est un coefficient qui caractérise le poli de la surface.L'intensité du reflet est donc proportionnelle au cosinus de l'angle β élevé à la puissancens. L'élévation à la puissance permet de rendre la fonction cosinus « pointue » : plus nsest grand, plus la région où la fonction vaut 1 se réduit. Donc le reflet n’est visible quedans une toute petite zone quand ns est grand.

Voici le graphe de cos(x)n avec différents exposants n : 1, 8, 32, 128 et 1024 ; xreprésente l’angle en radians entre -V et R.

6 11/09/2020

Page 7: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Cette équation modélise le reflet sur une surface parfaitement lisse. Nous verrons dans lasuite du cours comment d'autres surfaces sont modélisées. En général, les surfacescombinent les deux types d'éclairements : diffus et spéculaire.

Questions :

• Comment calcule-t-on le vecteur miroir de L par rapport à N ?

• Remarquer que l'angle β est entre R et -V ; R étant le miroir de L par rapport à N.On retrouve le même angle entre L et le miroir de -V par rapport à N. Lequel desdeux permet de limiter le nombre de calculs ?

- Programmer l'algorithme de calcul de la contribution RVB spéculaire qui s'ajoute àl'éclairement diffus.

À ce stade, les objets montrent une tache brillante indiquant visuellement la position deslampes.

Ombres portéesLes deux calculs précédents ne doivent pas être faits s'il y a un objet entre le point decontact et la lumière. Comment fait-on pour relancer un rayon à partir du point decontact pour tester cela ?

En fait, ce n’est pas du point de contact vers la lampe qu’il faut lancer le rayon, mais àl’inverse, sans quoi, on détecterait à tort des objets situés derrière la lampe. Il vaut mieuxlancer un rayon partant de la lampe et allant vers le point de contact du rayon initial etregarder si le premier contact de ce rayon désigne bien l’objet considéré : si c’est unautre objet qui est plus près de la lampe, alors le nôtre est dans son ombre.

- Programmer le test qui élimine certains calculs d’éclairement là où il y a une ombreportée.

RefletsOn peut ajouter une autre contribution à la couleur du point de contact : les couleurs desobjets qui se reflètent à cet endroit. Il « suffit » de relancer un rayon dans la directionmiroir du rayon actuel, de demander la couleur qu'on y voit et d'ajouter cettecontribution, modulée par Ks, à la couleur du point courant.

7 11/09/2020

Page 8: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Explication : la surface de sph3 est très lisse, la lumière qu'on voit venir du point C1provient en fait de la sphère sph8 au point C2. Le point C2 est situé sur le rayon partantde C1 dans la direction R miroir du rayon initial. Les calculs se font donc dans le sensinverse du parcours de la lumière.

Questions :

• Le calcul de la direction du vecteur R miroir de -V par rapport à N a déjà étéprogrammé, non ? Finalement, ça tombe assez bien.

• Comment relance-t-on un rayon dans cette direction ?

• Comment mélange-t-on la couleur du reflet avec la couleur du matériau ?

- Programmer l’ajout des reflets dans la fonction getColor.

À ce stade, les images deviennent très spectaculaires en montrant de très nombreuxreflets réalistes.

Que se passe-t-il si on doit dessiner deux surfaces localement planes face à face, quelrisque pour le programme ? Implémenter une solution : le paramètre supplémentairepassé à la fonction getColor limite la profondeur d'appel. On pourrait aussi accumulerl'opacité des surfaces et cesser les appels récursifs quand elle dépasse un seuil au-delàduquel le reflet n'est quasiment plus visible.

Mini-projetsCe qui suit sont des ajouts proposés. On retrouvera ces concepts avec OpenGL.Choisissez celui/ceux que vous voulez. Tous vont être présentés interactivement etexpliqués en séance autant que vous voudrez.

NB : le corrigé de tout ce qui précède vous sera fourni par mail (base-java.zip).

Important : pour la mise en œuvre, il faudra recopier à chaque fois le dossier lancer-Javaque vous avez obtenu (reflets, ombres portées…) et le renommer selon le projet voulu.Vous aurez ainsi : brume, antialias, blinn, damiers, pois, bosses, tranches, pastilles, plan,etc. Dans chacun de ces dossiers, on trouvera src, scenes ainsi que le Makefile. Ledossier scenes peut être placé au dessus, afin de le mettre en commun.

8 11/09/2020

Page 9: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Brume de distance

Comment peut-on ajouter un effet de brume de distance ? Il s’agit d’une couleur fixe quiremplace peu à peu la couleur des objets en fonction de la distance traversée par le rayonlumineux.

Elle intervient à différents niveaux : sur le rayon initial, et dans chaque rayon indirectlancé pour calculer les réflexions. À chaque fois, on utilise la distance du contact pourcalculer la densité de la brume. On calcule un paramètre k variant entre 0 et 1 (empêcherqu’il sorte de cette plage) qui est une fonction de la distance parcourue par le rayon, eton combine la couleur donnée par getColor avec la couleur de la brume par cetteformule :

Couleurfinale = k*Couleurbrume + (1-k)*CouleurPhong

- Programmer l’ajout de cette brume.

Vous noterez qu’il est difficile de régler l’intensité de cet effet car il dépend de la scène.

Anticrénelage (antialiasing)

Les bords des objets ne sont pas très élégants : il y a des marches d'escaliers. A quoi est-ce dû très précisément ? Pour corriger le problème, on emploie généralement latechnique du sur-échantillonnage : on lance plusieurs rayons par pixel de l'image.

C’est à dire que lors du dessin d’un pixel, on effectue 2x2 ou 3x3 (ou davantage) lancersde rayons très légèrement décalés, dans le même pixel, afin de le subdiviser de manièreégale. Soit un pixel (xe, ye). On veut le subdiviser en 3x3 sous-pixels. Le parcours devrase faire avec deux boucles imbriquées : pour dx=0 à 2, pour dy=0 à 2, lancer un rayonsur (xe+dx???, ye+dy???) : quelles sont les coordonnées exactes qu’il faut employer ?

Ensuite, on calcule la moyenne des couleurs obtenues pour obtenir celle du pixel.

- Programmer ce calcul dans la méthode TracerImage de la classe Lancer. On pourraitle coder dans CouleurPixel mais alors le dessin initial en mode brouillon ne serait plussi rapide, à moins de paramétrer cette méthode par le nombre d'échantillons – à vous devoir.

Voir plus loin pour une amélioration de cette technique.

Reflet spéculaire de Blinn

Blinn a proposé un autre calcul pour le reflet spéculaire. Au lieu de calculer (R.-V)ns * Ks *KL, Blinn introduit un vecteur H (half-vector) qui est sur la bissectrice entre L et -V. Ilsuffit de les additionner et normaliser le résultat. Ensuite, il calcule la teinte du refletspéculaire par :

9 11/09/2020

Page 10: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Couleurspéculaire = (N.H)ns * Ks * KL

Sa méthode est plus rapide que celle de Phong car il ne nécessite pas le calcul d’unvecteur miroir par rapport à N.

D’autre part, sur le plan physique, sa méthode semble meilleure. Examinez les reflets deslampes sur cette image suivante. Notez que la réflexion se produit sur une surface plane,ce qui n’est pas le cas des sphères.

Comparez les reflets spéculaires de ces deux images, lesquels semblent les plusréalistes ? Vous regarderez les boules de bowling différemment maintenant...

NB : pour une même valeur ns, les reflets de Blinn sont plus étalés que ceux de Phong. Ilfaudrait calculer (N.H)2ns pour obtenir approximativement le même résultat visuel.

Textures procédurales simples

Comment pourrait-on colorer les sphères avec des textures très simples comme des poisou des damiers ?

Une possibilité consiste à modifier la classe Objet3D et définir deux ensembles decouleurs diffuse et spéculaires. Ensuite il faudrait modifier la fonction de chargement etmodifier les fichiers. Dans les exemples ci-dessous, les couleurs sont simplement forcéesà du rouge quand on est dans la zone critique, donc toutes les sphères ont la mêmeapparence.

10 11/09/2020

Page 11: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

La méthode consiste à déduire des coordonnées sphériques locales : latitude et longitudeen fonction de la position relative du point de contact.

Comment calculez-vous des coordonnées sphériques à partir de coordonnéescartésiennes ? Demandez un schéma si vous ne voyez pas.

Ensuite, comment pouvez-vous savoir dans quelle zone se trouve le point de contact ?Une technique consiste à trouver une correspondance entre chaque coordonnée, latitudeet longitude, et un intervalle [0..N] avec N=nombre de pois ou de carrés, ensuite pourdes damiers, il faut regarder si la coordonnée est paire ou impaire, tandis que pour despois, il faut calculer une distance entre la coordonnée locale et son arrondi au plusproche entier (demander des explications au tableau).

Relief local

Comment pourrait-on dessiner des objets bosselés ou couvert d'encoches ?

C'est la même technique que pour les pois, mais au lieu de modifier les couleurs, onmodifie la direction du vecteur normal. C'est une simplification en trompe-l’œil. Lessphères restent parfaitement lisses. On altère la direction des normales au moment ducalcul d'éclairement. On fait pencher la normale dans un sens ou l'autre selon la positiondu point de contact sur l'objet.

11 11/09/2020

Page 12: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Tranches et pastilles

Encore un autre délire : faire en sorte que les sphères soient incomplètes comme audessus. Le principe consiste à modifier la fonction de calcul d’intersection afin qu’elleignore les intersections quand le point de contact est dans certains intervalles de hauteurrelative ou dans des pois. Voir le mini-projet précédent.

Pour ces deux effets, il faut calculer la position du point de contact à l’intérieur de lafonction d’intersection, pour en déduire sa position relative, puis ses coordonnéeslongitude et latitude et enfin déterminer si le contact est effectif ou pas. C’est donc trèscoûteux en temps de calcul.

Un dernier point concerne le calcul du vecteur normal. Si on voit « l’autre côté » de lasphère, alors il faut en inverser la direction. C’est le cas quand on élimine l’un des pointsd’intersection. Vous devrez donc rajouter un booléen à la classe Sphère pour savoir si lepoint de contact est à l’intérieur ou à l’extérieur.

Dessin plus efficace

Vous pouvez aussi décider d’améliorer la vitesse de calcul des images, notamment quandil y a de l’anticrénelage. Deux pistes sont possibles : faire un anticrénelage adaptatif etutiliser des threads.

Anticrénelage adaptatif

Le principe reste de subdiviser chaque pixel en sous-pixels et de calculer une teintemoyenne. Cependant, la majorité des pixels a une teinte très homogène. C’est le cas duciel ou d’un objet non réfléchissant. La subdivision complète d’un pixel est intéressantelorsqu’on est sur un bord d’objet ou qu’il y a des textures ou reflets très contrastés.

L’idée est donc de lancer un rayon dans chaque « coin » du pixel à dessiner. Si les 4 coinssont presque de la même couleur (seuil à définir), et éventuellement sont sur le mêmeobjet, alors on se contente de la moyenne de ces 4 rayons. Si au moins l’un des coinsmontre une couleur trop différente des autres, ou qu’il n’est pas sur le même objet, alorson lance des rayons sur la totalité des sous-pixels.

Dessin multitâches

Le principe est de séparer l’image en plusieurs zones et de confier les calculs à destâches séparées. C’est un pur problème de parallélisation de l’algorithme avec lesdispositifs Java. Il faut étudier les Callable et les ExecutorService.

12 11/09/2020

Page 13: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Plan horizontal infini (difficile)

Le but est de dessiner différents types d’objets, au lieu de seulement des sphères. Onvoudrait ajouter un type « plan horizontal ».

Pour cela, il faut dériver la super-classe Objet3D avec une nouvelle classe, PlanXZ. Laméthode Intersection est abstraite dans Objet3D et doit être définie dans chaquesous-classe, car le calcul des intersections avec une droite est spécifique – il donne laforme de l’objet ; De même, le calcul de la normale doit être défini par chaque objet.

Un plan horizontal est défini par l’équation y=y0. Le calcul de l’intersection avec unrayon est donc très simple. Le paramètre y0 peut être tiré de la variable centre.

Les fous pourront s’amuser à plaquer une texture (damier, pois) sur le plan. Dans l’imageprécédente, j’ai utilisé la couleur diffuse et l’ai éclaircie ou assombrie selon lescoordonnées relatives.

Bulles de fumée (très difficile)

Au lieu de dessiner des sphères pleines et opaques, on calcule comme si elles contenaientuniquement de la fumée (ce projet ne doit pas vous inciter à fumer…).

La réalisation de cet effet est relativement complexe quoique le principe soit assezsimple. On ne s'intéresse qu'aux sphères qui ont deux intersections avec le rayon initial.Ces deux intersections forment une sorte de segment [d1, d2]. Il y a de la fumée entre cesdeux distances. La couleur du pixel dépendra de l’écart entre d1 et d2.

Ensuite, au lieu de ne chercher que la sphère la plus proche, on considère toutes lessphères que traverse le rayon initial. On construit la liste de tous les segments traversés :[d1, d2] ∪ [d'1, d'2] ∪ [d"1, d"2] … Le plus difficile arrive car il faut fusionner les

13 11/09/2020

Page 14: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

segments qui se recouvrent. Par exemple, [3, 6] ∪ [4, 8] = [3, 8], mais [3, 6] ∪ [ 8, 10]reste inchangé.

La complexité est dans la gestion algorithmique d'une liste de Segment. Chacun estreprésente un intervalle [d1, d2]. Vous devrez écrire une méthode qui tente de fusionnerun segment avec un autre – cet autre disparaît alors de la liste le cas échéant. Pensezaussi à l'ajout d'un segment qui en fait fusionner deux : [3, 6] ∪ [ 8, 10] à laquelle onrajoute [5, 9] devient [3, 10]. La densité de la fumée est alors proportionnelle à la sommedes largeurs des segments restants.

Réfraction (très difficile)

Le but serait de dessiner des objets transparents : la lumière passe au travers en étantdéviée selon la loi de Snell-Descartes. Dans l’image ci-dessous, les deux grandes sphèresdu premier plan réfractent la lumière, dont celle d’une sphère bleue cachée derrière.

Le calcul de la direction du rayon réfracté, non trivial, est expliqué à la fin de cet énoncé.Il est complexe mais pas infaisable. L'obstacle principal réside dans la gestion des indicesde réfraction. Quand un rayon rentre dans une sphère, il passe d'un indice n i=1 à l'indicenr=1.5 (verre), quand il quitte la sphère il repasse de n i=1.5 à nr=1 (donc η est inversé). Ilfaut donc savoir d'où vient ce rayon : de l'extérieur ou de l'intérieur ? On peut ajouter unbooléen à la classe Rayon pour gérer l'information.

Sur l’image précédente, on peut s’apercevoir que la réfraction se produit au centre desobjets, car sur les bords, c’est seulement la réflexion qui domine. C’est le cas dans lanature, voir l’image ci-dessous. Lorsque le regard plonge assez droit dans l’eau, on voit lefond ; lorsqu’il rase l’eau, on ne voit que le reflet. Ce n’est pas du tout lié à la profondeurde l’eau. La profondeur, elle, joue sur la teinte qui revient du fond : un peu comme labrume, elle est altérée en fonction de la distance parcourue dans l’eau. La raison dupartage entre réfraction et réflexion est une question d’électromagnétisme et a étémodélisée par Fresnel, voir https://fr.wikipedia.org/wiki/Coefficient_de_Fresnel.

14 11/09/2020

Page 15: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

La couleur effective est donc un mélange de la réflexion et de la réfraction dépendant del’angle entre N et V. Elle est calculée par : rt*Réflexion + (1-rt)*Réfraction avec rt est unparamètre qui vaut R0 + (1 – R0) * (1 – (N.V)5) (modélisation de Schlick pour simplifiercelle de Fresnel) avec R0 calculé par (1 – η)² / (1 + η)², η étant le rapport des indices deréfraction entrant/sortant. Attention, comme pour le calcul du rayon réfracté, ce rapportdépend du milieu d’arrivée et du milieu de sortie du rayon : c’est 1/1.5 quand le rayonvient de l’air et qu’il rentre dans du verre, et c’est 1.5/1 quand le rayon sort du verrepour retourner dans l’air.

Le problème, c'est quand on accepte que plusieurs sphères soient emboîtées l'une dansl'autre. Ça rappelle le projet précédent avec la fumée. La sortie du rayon se fait dans ladernière sphère traversée, mais chaque surface traversée ajoute ses réflexions internes.

Ombres douces (difficile)

On voudrait obtenir l’image suivante, dans laquelle les ombres ne sont pas nettes,indiquant la présence de lampes non ponctuelles. Nb : les reflets ont été rendus plussombres afin de mieux voir les ombres portées ainsi que les dégradés le long des sphères.

La technique est un peu folle. Elle consiste à simuler une sorte de nuage de lampes aulieu d’une seule, ceci pour chaque lampe.

15 11/09/2020

Page 16: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

Les calculs d’éclairement, c’est à dire le test d’ombres portées et les calculs diffus etspéculaire, sont répétés pour chaque vecteur Lu dérivé de L, et toutes les contributionssont additionnées.

Le problème est de générer les variantes du vecteur L. Une idée assez simple consiste àincliner le vecteur L d’un angle variant entre -limite et +limite, cette limite valant parexemple 5° (cette constante et le nombre de pseudo-lampes sont à placer dansConstantes.java, ou seraient à rajouter au fichier de définition des scènes). U est unvecteur orthogonal à L, donnant l’axe de la rotation. Alors en réalité, le vecteur L ne doitpas être incliné seulement dans un plan, mais dans deux directions orthogonales U et V,afin de balayer une sorte de cône à base carrée.

Il faut :

1) Calculer deux vecteurs U et V orthogonaux entre eux et avec L. (L,U,V) forme unebase orthonormée au point de contact. Pour cela, un calcul simple fait appel auproduit vectoriel, programmé dans la méthode Vecteur.cross. Il sera expliquédans le chapitre 3 du cours. Il faut seulement savoir que cross(A,B) retourne unvecteur orthogonal à A et B à condition que A et B ne soient pas colinéaires.

Ici, on propose de calculer U = Vecteur.cross(L, M) puis V = Vecteur.cross(L, U)avec un vecteur M valant (1,0,0) si |L.x| < |L.y| ou |L.x| < |L.z| ; sinon M=(0,1,0) si|L.y| < |L.x| ou |L.y| < |L.z| ; sinon M=(0,0,1). Le but est que M ne soit pas alignéavec L pour pouvoir faire le premier produit vectoriel.

2) Imbriquer deux boucles pour faire varier u entre -limite et +limite et v entre entre-limite et +limite également. Calculer Lu = Vecteur.rotate(L, U, u) et Luv =Vecteur.rotate(Lu, V, v). La méthode Vecteur.rotate(vecteur, axe, angle) estprogrammée dans Vecteur.java ; elle applique une rotation au vecteur de l’angleen radians, autour de l’axe indiqué, et retourne le vecteur résultant. Pensez aussiun peu à l’efficacité des calculs en plaçant ces instructions là où elles ne seront pasrépétées inutilement.

3) Calculer l’éclairement avec Luv et additionner toutes les contributions en divisantà la fin par le nombre total de contributions de ce genre.

16 11/09/2020

Page 17: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

TP n°1 - solution

RéfractionSoit ni l'indice du milieu contenant le rayon incident et nr l'indice du milieu du rayonréfracté. L'indice de l'air est 1, l'indice de l'eau est environ 1.33 et celui du verre environ1.5, voir https://fr.wikipedia.org/wiki/Liste_d%27indices_de_r%C3%A9fraction.

Soit I le vecteur incident, R le vecteur réfracté, N le vecteur normal, T le vecteur tangent.Ces vecteurs sont tous normés. I et N sont connus, T et R sont inconnus, R est àdéterminer en fonction de I et N. Attention, I est dirigé vers la surface, tandis que R ensort.

Soit ai l'angle entre N et -I. Soit ar l'angle entre -N et R.

On a : 1cos a i=−I.N qui doit être positif. De même, cos(ar), voir plus loin, doit êtrepositif.

Loi de Snell-Descartes sur la réfraction : n i⋅sin a i=nr⋅sin ar

On en tire :

et

On exprime ensuite I et R en fonction de N et T qui sont considérés comme formant unebase orthonormée, même si T n’est pas connu, attention aux signes :

Le but est d'exprimer R uniquement avec des éléments connus : I et N et les indices desmilieux traversés. On va remplacer tous les éléments inconnus de (4) par des élémentsconnus.

On commence par le terme sin(ar).T. De l'équation (3), on tire :

17 11/09/2020

4 R=−cos ar⋅Nsin ar⋅T

3 I=−cos a i⋅Nsin a i⋅T

5T=1

sin a i⋅ Icosai⋅N

2 ' sinar

sin a i=

ni

nr

2sin ar=ni

nr

⋅sinai

Page 18: TP n°1 : lancer de rayonsTP n 1 : lancer de rayons Le but du TP est de concevoir complètement un programme de synthèse d'images par lancer de rayons. Ce programme ne sera pas optimisé,

On cherche la valeur du terme sin(ar).T qui se trouve dans (4) à l’aide de (5) :

A l’aide (2') et (1), on remplace le quotient de sinus et le cosinus ainsi :

On modifie l'équation (4) à l'aide de (6) :

Il reste à exprimer cos(ar) en fonction des éléments connus : I, N et les indices desmilieux.

On part de l'équation trigonométrique classique, ré-écrite en :

7cos a 2=1−sin a

2

c'est à dire pour ar, avec l'équation (2) :

soit encore, avec l'équation trigonométrique (7) et la (1) mise au carré :

Dans le déroulement du calcul, on devra d'abord calculer k qui représente cos²(a r) avec laformule (8). Ce nombre k devra être testé, car il ne doit pas être négatif ou nul : le rayonlumineux ne serait pas réfracté.

Finalement, on obtient ceci :

Il est fréquent de représenter le rapport des indices par la lettre grecque η (eta).

NB : ce calcul est effectué par la fonction refract de GLSL.

18 11/09/2020

cos ar2=1−

ni

nr

2

∗sina i2

sin ar⋅T=sinar

sin a i⋅ Icosai⋅N

6sin ar⋅T=ni

nr

⋅ I− I.N ⋅N

3R=−cos ar⋅N n i

nr

⋅ I− I.N ⋅N

8k=cos ar2=1−

ni

nr

2

⋅1− I.N 2

9R=ni

nr

⋅I−ni

nr

⋅ I.N k ⋅N