Lancer de rayons - Extensions



Aller plus loin

Pour améliorer votre raytracer, voici une liste (non-exhaustive) d'extensions possibles classées par catégories. Un niveau indicatif de difficulté est indiqué.

Pensez encore une fois à aller consulter les diapositives du cours du MIT qui couvrent certains de ces sujets.

Si vous créez vos propres scènes et voulez placer la caméra précisément, utilisez le viewer pour placer la caméra où vous le souhaitez puis quittez avec Escape. Le fichier .qglviewer.xml contient alors le Frame de la caméra.

Nouveaux objets

Contrairement à la sphère, ces nouveaux objets sont sensibles à leur orientation (définie par leur frame()). Calculer l'intersection d'un rayon avec (par exemple) un cylindre arbitrairement positionné et orienté est difficile. Il est bien plus simple de faire l'inverse : placer le rayon dans le repère du cylindre (qui est alors défini comme aligné avec un axe) pour y faire les calculs. Le résultat (Hit) n'aura ensuite qu'à être re-transformé dans le repère monde.

La transformation du Frame étant une transformation rigide, les distances ne sont pas modifiées et la comparaison du temps d'impact reste valable. Les méthodes de la classe qglviewer::Frame permettent de très facilemement convertir d'un repère à un autre.

Vous ajouterez donc une méthode qui convertit un Ray du repère monde au repère de l'objet, ainsi que la méthode inverse dans Hit pour remettre le résultat dans le repère monde.

Plans - Niveau 1

Pétanque La structuration claire de votre programme doit vous permettre d'ajouter la gestion de l'objet "plan" (infini) en plus des sphères en peu de temps. On décide qu'un plan passe par l'origine et a pour normale l'axe z, définis dans le Frame associé (hérité de Object).

Si vous voulez créer vos propres scènes, la méthode Quaternion(Vec(0,0,1), votreDirection) vous permet de trouver le Quaternion associé à une normale donnée.

Le plan étant infini, son boundingRadius sera empirique. Cette valeur ne sert de toutes façons qu'au viewer OpenGL pour ne pas clipper des parties de la scène. Deux plans

Les fichiers petanque.scn, deuxPlans.scn et rayure.png vous permettront de reproduire ces images.

Cette dernière contient simplement trois sphères et deux plans orthogonaux. La scène y semble pourtant dupliquée 3 fois du fait des réflexions.

Triangles - Niveau 1

Le triangle est un peu plus complexe dans sa méthode intersect, mais reste simple à implémenter. Les deux faces d'un triangle jouent-elles le même rôle ? À vous de choisir.

Surfaces triangulées - Niveau 1

Le plus difficile est de bien définir le format de données. Il suffit ensuite d'utiliser les méthodes du triangle. La palette de scène s'en trouve par contre bien élargie, au prix d'un temps de calcul croissant.

Cylindres - Niveau 2

Cylindres Pour les cylindres, on pourra, en plus de la hauteur, donner deux rayons différents aux deux bases du cylindre pour genérer une plus grande diversité. Les calculs d'intersection sont un peu plus complexes. Indice pour draw() : gluCylinder.

Surfaces splines - Niveau 3

La difficulté est ici de calculer l'intersection de la surface avec le rayon. Il faudra également bien choisir la manière de définir la surface. La mise au point de l'algorithme grâce à l'interface OpenGL peut s'avérer utile.

Surfaces de subdivision - Niveau 3

Le problème est similaire aux surfaces splines. Il faut de plus bien assimiler le principe de ces surfaces. On se limitera à un schéma de subdivision simple.

Constructive Solid Geometry - Niveau 3

Pour pouvoir faire de la CSG, il faut conserver toutes les intersections qui ont eu lieu le long d'un rayon, afin de pouvoir choisir celle qui sera conservée. Le cours du MIT donne quelques pistes.

Phénomènes optiques

Perturbation de normales - Niveau 1

Il est très facile de rendre les objets moins lisse en perturbant très légèrement leur normale lors du calcul. On peut chercher à définir le(s) paramètre(s) adéquat(s) permettant de facilement modifier le matériau pour celà.

Une autre méthode, très souvent employée consiste à fournir la modification de normale sous forme d'une texture de bump map (x,y et z étant codés dans R, G et B) que l'on accède via les coordonnées u,v précédemment définies (voir ce site pour un exemple sur les planètes).

Cartes d'environnement - Niveau 1

Spherical Map Lorsqu'un rayon n'intersecte aucun objet, au lieu de lui donner la couleur de fond de la scène, on va chercher dans une image représentant l'environnement sa couleur. Cette image peut être une carte cubique (6 textures sur les faces d'un cube) ou une (ou deux) carte sphérique (photo de la scène reflétée dans une sphère métallique). Il suffit de calculer correctement les coordonnées du pixel correspondant au rayon.

Réflection de Fresnel - Niveau 2

La reflectiveColor d'un matériau est en fait fonction de l'angle sous lequel est vu la surface. Elle augmente aux angles rasants. C'est ce qui fait que le lino du fond d'un couloir semble réfléchissant alors qu'il ne l'est pas quand on le regarde sous nos pieds.

La formule exacte et son approximation avec un cosinus puissance 5 sont dans le cours du MIT.

Lampes atténuées - Niveau 2

L'intensité des lampes utilisées ne dépend pas de la distance à la source. Elle devrait en fait varier comme l'inverse de cette distance au carré. Ajoutez trois paramètres a,b et c à vos sources, qui viendront diminuer l'intensité de la source selon I = a - b/d - c/(d^2) (où d est la distance à la source).

Une autre extension consite à gérer les lampes spot (voir la documentation de glLight). Ces lampes directionnelles ont une intensité qui décroit lorsqu'on s'éloigne de la direction principale, et qui finit par s'annuler.

Réfraction - Niveau 3

La réfraction du rayon permet de simuler des objets transparents. Il faut définir un coefficient de réfraction du matériau, et se souvenir de si le rayon est à l'intérieur au non, pour appliquer la réfraction inverse à la sortie du matériau.

Cette extension est relativement complexe et risque de révéler des bugs dans le reste de votre code. On se réferera encore une fois au cours du MIT où le principe et quelques détails d'implémentation sont donnés.

Dernière extension : ne plus considérer les objets transparents comme totalement opaques et projetant des ombres. Les voir davantage comme des filtres qui colorent la lumière (en toute première approximation). A discuter lors de la soutenance.

Qualité de rendu

Prévisualisation - Niveau 1

Affichez sur le plan semi-transparent de la caméra une image (plus ou moins grossière) de la scène calculée par lancer de rayon.

Affichage OpenGL - Niveau 2

Le but de cette extension n'est pas d'améliorer votre lancer de rayon, mais le prévisualiseur OpenGL ! On pourra utiliser les pixels shaders pour implémenter un phong par pixel, et les shadow map pour simuler les ombres.

Ne vous lancez dans cette extension que si vous maîtrisez suffisement OpenGL et qu'elle vous intéresse, par exemple pour votre stage. Attention, les cartes graphiques des machines de l'ARV ne supportent pas le pixel shader, et il vous faut donc une machine personnelle adaptée.

On réfléchira aux avantages et aux limitations d'un rendu hardware par rapport au lancer de rayon.

Anti-aliassage - Niveau 2

On peut améliorer les résultats en pondérant les couleurs des rayons correspondant à un pixel par un noyau gaussien (centré sur le centre du pixel), plutôt qu'en moyennant simplement les couleurs. Il est plus souple de coder une classe Filter qui donnera les poids ainsi que les décalages (par rapport au centre du pixel) associés à chaque rayon. Cette classe pourra également sauvegarder une image en niveaux de gris du filtre utilisé. Voici les résultats obtenus sur des grilles nxn, pour n=1, 2, 3 et 4 (images grossies 3 fois):
Gaussian filtering 4 Gaussian filtering 3 Gaussian filtering 2 Gaussian filtering 1
On commentera ces résultats lors de la soutenance, en présentant une discussion sur les filtres utilisés (pourquoi une gaussienne, pourquoi un support plus grand que le pixel ?).

Ombres douces - Niveau 3

Une source étendue génère des ombres douces beaucoup plus réalistes. Il ne suffit plus de savoir si un point est dans l'ombre ou pas, mais quel pourcentage de la source est visible depuis ce point. Cela peut s'approximer en échantillonnant la surface de la source et en comptant quel pourcentage de rayons voit la source.

La méthode peut rapidement gréver votre temps de rendu, et on réfléchira à des heuristiques pour l'accélérer (même si on ne les code pas).

Optimisations

Grille - Niveau 3

Pour accélérer les calculs d'intersection, en particulier avec une surface triangulée, on peut plonger la scène dans une grille régulière (éventuellement hiérarchique), dont chaque cellule connait les objets dont la surface les intersecte.

Il y a deux difficultés : associer les objets aux différentes cellules et parcourir cette grille avec unrayon. Cette optimisation est largement détaillée dans l'assignement 5 du TP du MIT.

Autres optimisations - Niveau 3

En cherchant sur le web, on trouve facilement des solutions d'optimisation diverses (voir par exemple ici), que l'on pourra chercher à implémenter. On essaiera surout d'en prévoir les bénéfices, et à les comparer à la difficulté d'implémentation.