Auteur : César Charbey
Ce projet a pour but de développer un moteur de lancer de rayons (Raytracer) complet en C++ / OpenGL. Partant d'une structure minimale, j'ai implémenté progressivement les concepts fondamentaux pour aboutir à un moteur capable de simuler des phénomènes physiques complexes comme la réfraction, les caustiques et l'illumination globale approximée.
La première étape consistait à mettre en place le mécanisme fondamental du Raytracing. Contrairement à la lumière réelle, nous lançons les rayons depuis l'oeil (la caméra) à travers chaque pixel de l'écran virtuel pour déterminer ce qu'ils touchent.
-
Sphère : Résolution analytique d'une équation du second degré
$|P(t) - C|^2 = R^2$ . - Carré : Intersection plan infini + vérification des bornes locales.
| Sphère | Carré | Assemblage (Cornell Box) |
|---|---|---|
![]() |
![]() |
![]() |
J'ai implémenté le modèle local de Phong qui décompose la lumière en trois composantes :
-
Ambiante (
$I_a$ ) : Lumière constante. -
Diffuse (
$I_d$ ) : Proportionnelle à$\cos(\theta) = N \cdot L$ . -
Spéculaire (
$I_s$ ) : Tache brillante proportionnelle à$(R \cdot V)^\alpha$ .
Pour pallier le manque de réalisme des ombres dures, j'ai implémenté des Area Lights.
L'algorithme repose sur une méthode de Monte-Carlo : je lance
Résultat : Sphères avec éclairage de Phong et ombres douces.
Chargement de fichiers .OFF et stockage dans une classe Mesh.
J'ai implémenté le Smooth Shading : lors du chargement, je pré-calcule la normale moyenne de chaque sommet. Lors du rendu, j'interpole la normale via les coordonnées barycentriques :
Pour l'intersection Rayon-Triangle, j'utilise l'algorithme de Möller–Trumbore. Il est rapide, économe en mémoire (pas de stockage de plan) et fournit directement les coordonnées barycentriques
J'ai introduit la récursivité pour gérer les matériaux complexes.
-
Réflexion (Miroir) : Calcul du vecteur réfléchi
$R = I - 2(N \cdot I)N$ . -
Réfraction (Verre/Eau) : Utilisation de la loi de Snell-Descartes
$n_1 \sin(\theta_1) = n_2 \sin(\theta_2)$ .- Gestion entrée/sortie du milieu (inversion des normales et des indices).
- Gestion de la réflexion totale interne.
- Fresnel (Schlick) : Approximation pour mixer réflexion et réfraction selon l'angle de vue (plus réflectif sur les bords).
| Réfraction Standard | Effet Fresnel / Rasant |
|---|---|
![]() |
![]() |
| Le rayon traverse | Le rayon est réfléchi |
Pour optimiser le rendu des maillages complexes, j'ai implémenté un KdTree à deux niveaux (Architecture BVH).
- Niveau 1 (Global / TLAS) : Structure la scène. Il contient les Objets (Sphères, Meshs, Plans). Permet un Culling efficace.
-
Niveau 2 (Local / BLAS) : Interne au
Mesh. Gère les milliers de triangles d'un objet. Utilise une traversée optimisée par pile itérative ($O(\log N)$).
Cette architecture sépare la logique de la scène de la géométrie pure. Elle correspond au standard industriel utilisé par les GPU modernes (RTX) sous les noms de TLAS (Top-Level Acceleration Structure) et BLAS (Bottom-Level Acceleration Structure).
| KdTree Simple (1 niveau) | KdTree Complexe (2 niveaux) |
|---|---|
![]() |
![]() |
Références : ARM Developer | Vulkan Tutorial
Remplacement de Phong par Blinn-Phong (utilisation du Half-Vector
| Phong Classique | Blinn-Phong |
|---|---|
![]() |
![]() |
Implémentation d'une passe de Lancer de Photons pour générer des caustiques (lumière focalisée par le verre).
- Émission de millions de photons depuis la lumière.
- Stockage dans une Photon Map (via un KdTree spécifique).
- Estimation de densité lors du rendu final (k-NN).
| Sans Photons | Avec 1M Photons | Debug PhotonMap |
|---|---|---|
![]() |
![]() |
![]() |
| Ombres noires | Caustiques visibles | Nuage de points |
Références : Alchetron | Wikipédia
Création d'une eau procédurale (fonctions sinusoïdales) et simulation de l'absorption de la lumière (Brouillard/Beer-Lambert).
Application d'une courbe de Tone Mapping pour gérer la plage dynamique (HDR) et éviter la saturation des blancs ("clamping") due aux caustiques intenses.
| Sans Tone Mapping | Avec ACES |
|---|---|
![]() |
![]() |
| Saturation brutale | Détails préservés |
Intégration d'une interface graphique pour le contrôle temps réel :
- Choix de scène.
- Position de la lumière / Puissance.
- Paramètres de rendu (Samples, Nb Photons).
- Debug (Visualisation KdTree, Photons).
Voici quelques "accidents" rencontrés durant le développement.
| "Varicelle" (Photons trop gros) | Miroir infini | Création de l'eau |
|---|---|---|
![]() |
![]() |
![]() |
| Cornell Box (1M Photons) | Scène Sous-Marine (100M Photons) |
|---|---|
![]() |
![]() |
Rendu Haute Qualité 10 millions de photons / 20 samples / HD / 389 secondes

























