Construire un ray tracer — 01 — Générer les rayons caméra

La première brique du moteur : transformer chaque pixel en un rayon dans le monde. Du centre du pixel aux NDC, à l'espace écran avec le format et le champ de vision, puis au monde via la matrice caméra.

01 — Générer les rayons caméra

Ce que tu vas apprendre

  • Comment transformer un pixel en rayon, étape par étape
  • Le rôle du format (aspect ratio) et du champ de vision
  • Le passage de l'espace caméra à l'espace monde
  • Le code complet de génération d'un rayon

Prérequis


En ray tracing, tout commence par un rayon par pixel. Générer ces rayons, c'est le pipeline de projection de la série caméra, mais parcouru à l'envers : au lieu d'aller d'un point 3D vers un pixel, on part du pixel pour fabriquer le rayon qui s'enfonce dans la scène. Voici la procédure exacte, telle que Scratchapixel la détaille.

Étape 1 — Pixel → NDC

On part des coordonnées pixel (i, j) (raster space, origine en haut à gauche). On vise le centre du pixel, d'où le + 0.5, et on normalise dans [0, 1] :

PixelNDC.x = (i + 0.5) / largeurImage
PixelNDC.y = (j + 0.5) / hauteurImage

Étape 2 — NDC → espace écran

On remappe dans [-1, 1] et on retourne le y (en raster, y descend ; en écran, y monte) :

PixelScreen.x = 2 × PixelNDC.x − 1
PixelScreen.y = 1 − 2 × PixelNDC.y

Le centre de l'image est maintenant à (0, 0), les bords à ±1.

Étape 3 — Format et champ de vision

Deux corrections pour que le rayon parte dans la bonne direction.

Le format (aspect ratio). Une image rectangulaire déformerait les pixels si on n'y prenait garde. On multiplie le x par le rapport largeur/hauteur :

aspect = largeurImage / hauteurImage
PixelCamera.x = PixelScreen.x × aspect

Le champ de vision. Avec le plan image placé à 1 unité de la caméra, l'ouverture du champ de vision α étire les coordonnées d'un facteur tan(α/2) :

PixelCamera.x = PixelScreen.x × aspect × tan(α/2)
PixelCamera.y = PixelScreen.y × tan(α/2)

Plus le champ de vision est large, plus tan(α/2) est grand, plus les rayons s'écartent — exactement l'effet grand-angle.

Étape 4 — Espace caméra → monde

Dans l'espace caméra, le point visé sur le plan image est (PixelCamera.x, PixelCamera.y, -1) (le -1 car la caméra regarde vers les z négatifs). L'origine du rayon est la position de la caméra, soit (0, 0, 0) en espace caméra.

On transforme ces deux points par la matrice caméra-vers-monde (celle de LookAt), puis la direction est le vecteur du premier vers le second, normalisé :

O' = cameraToWorld × (0, 0, 0)
P' = cameraToWorld × (PixelCamera.x, PixelCamera.y, -1)
directionRayon = normalize(P' − O')

Le code complet

Mis bout à bout, générer un rayon tient en quelques lignes :

cppfloat aspect = imageWidth / (float)imageHeight;
float scale  = tan(fov * 0.5f * M_PI / 180.f);   // fov en degrés → tan(α/2)

float x = (2 * (i + 0.5f) / imageWidth  - 1) * aspect * scale;
float y = (1 - 2 * (j + 0.5f) / imageHeight)          * scale;

Vec3f rayOrigin    = cameraToWorld * Vec3f(0);
Vec3f rayDirection = normalize(cameraToWorld * Vec3f(x, y, -1) - rayOrigin);

rayOrigin et rayDirection définissent le rayon O + t·D qu'on va lancer dans la scène. Tous les pixels partagent la même origine (la caméra) ; seule la direction change.

L'inverse de la rasterization

Remarque le renversement par rapport à la série caméra : en rasterization, on multipliait par la matrice monde-vers-caméra (l'inverse) pour amener les points dans l'espace caméra. Ici, on multiplie par la matrice caméra-vers-monde (directe) pour envoyer les rayons dans le monde. Même matrice, sens opposé — c'est toute la différence entre projeter la scène sur l'écran et lancer des rayons depuis l'écran.

Le rayon est prêt. L'article suivant le lance dans une scène d'objets simples et retrouve la boucle de rendu, avant d'attaquer les triangles.


Sources

  • Scratchapixel. Generating Camera Rays with Ray-Tracing. scratchapixel.com
  • Shirley, P. Ray Tracing in One Weekend, section « Rays, a Simple Camera, and Background ». raytracing.github.io
  • Marschner, S., & Shirley, P. (2021). Fundamentals of Computer Graphics (5ᵉ éd.), chap. « Ray Tracing ». CRC Press.

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.