L3 synthèse d'images
2023

TP2 - lancer de rayons et lumières


le tp1 permet de calculer une premiere image, avec quelques objets éclairés par un soleil, ou à l'ombre.


Partie 1 : plusieurs soleils !

avant de se lancer dans le calcul complet qui permet d'éclairer les objets avec un soleil et un ciel, on va regarder un cas plus simple : avec 2 soleils !
qu'est ce qui change ? on va faire 2 fois le même calcul : une fois par soleil et ajouter les 2 résultats. la lumière réfléchie par un objet éclairé par 2 sources de lumière est la somme de la lumière réfléchie par chaque source.

et les ombres ? l'objet peut être à l'ombre des 2 sources, ou d'une seule, ou d'aucune. encore une fois, on additionne les 2 resultats : pour chaque source de lumière l'objet est éclairé ou pas, et c'est ce résultat que l'on additionne.

vérifiez que vous obtenez un résultat cohérent, par exemple :



vous pouvez reproduire ce résultat avec les directions : normalize(Vector(-4, 6, 1)) et normalize(Vector(4, 6, -1))
on observe bien le sol complètement noir sous la sphère, ie aucun soleil n'éclaire cette partie. on a bien des ombres plus claires à gauche et à droite de la sphère, ie 1 seul soleil éclaire dans ce cas et l'autre est à l'ombre.


Partie 2 : et le ciel ?

exercice 1 :
relisez le cours pour générer des directions (aléatoires ou pas) et calculez une image, c'est le même principe qu'au dessus, mais avec plus de directions.

attention : les directions calculées par le code du cours sont à moitiée au dessus du point p à la surface de l'objet et à moitiée en dessous, avec un cos theta < 0 (ie l'angle entre n, la normale au point p, et la direction l, vers le soleil / ou le ciel).
on ne fait le calcul que pour les directions au dessus du point, ie avec cos_theta > 0. comment détecter ces directions et éliminer les autres ?

mais pourquoi ? on pourrait aussi générer des directions dans une hemisphère et pas dans une sphère complète, mais il faut ensuite transformer ces directions pour les aligner avec la normale du point p. la solution proposée qui évite de manipuler ces transformation est un final plus simple.


exercice 2 :
mais toutes les directions au dessus du point p ne voient pas le ciel non plus... il faut en plus que la direction soit au dessus de l'horizon, pas au dessous.
comment vérifier que c'est le cas ?

rappel : la couleur du ciel correspond au terme Le( l ) dans les calculs, ie la lumière émise par la source qui arrive au point p depuis la direction l, et Le( l ) > 0 si l est au dessus de l'horizon et 0 sinon.
indication : on va encore utiliser le produit scalaire entre 2 vecteurs, l bien sur et quel autre vecteur ?


exercice 3 :
pour l'instant, l'image est noire pour tous les pixels qui ne "voient" pas un objet. et par définition, les rayons du pixel qui ne voient pas un objet, voient... le ciel ! modifiez la couleur du pixel dans ce cas.


exercice 4 :
et avec un ciel coloré ? comment modifier la couleur du ciel en fonction de la direction l ? par exemple, au lever du soleil, les directions juste au dessus de l'horizon n'ont pas la même couleur que les autres directions. idem au coucher du soleil.
vérifiez que cette couleur du ciel qui dépend de la direction est bien prise en compte pour calculer la lumière réfléchie vers le pixel dans tous les cas : lorsque le pixel observe un objet, ou lorsqu'il observe le ciel.

utilisez des objets gris, de couleur neutre, cf Color(0.5) par exemple, pour vérifier que l'éclairage est cohérent...
et n'oubliez pas que les couleurs sont des float entre 0 et 1.

vérifiez également que Red() * Blue() == Black()... cette dernière remarque devrait vous aider à choisir des couleurs un peu plus nuancées, ie le produit de 2 couleurs primaires est noir, par définition.





Intermède : plus vite ?

si vous avez écrit la partie 6 "anti-aliasing" du tp1, le temps de calcul pour obtenir une image propre doit commencer à augmenter...
pourquoi ? comptez combien de fois vous faites le calcul éclairé / à l'ombre par pixel. si vous avez ajouté plus d'objets, comment évolue le temps de calcul ?
ou rappelez-vous la complexité des algorithmes vu en LIFAPC ? combien y a t il de boucles pour calculer un pixel, pour toute l'image ?

en gros votre code doit ressembler à :

pour chaque pixel :
    pour chaque rayon dans le pixel :
        trouver l'objet visible (ie boucle de calcul d'intersection pour chaque objet)

        pour chaque direction dans le ciel :
            vérifier que le point p est éclairé (ie boucle de calcul d'intersection pour chaque objet)
            accumuler la lumière réfléchie vers le pixel

il existe une solution assez simple pour mieux controler le temps de calcul complet de l'image, mais il faut utiliser des directions aléatoires dans la partie 2 pour éclairer les objets  avec N directions (aléatoires) dans le ciel. il suffit de n'utiliser qu'une seule direction aléatoire dans le ciel et de recommencer pleins de fois par pixel.
et oui ca marche, ces 2 manières de faire le calcul convergent vers le meme résultat / la même image. les détails seront dans le cours de M2, par contre...