En 2026, des démos publiques où Claude construit des scènes 3D dans le navigateur ont commencé à circuler parmi les développeurs. Nous avons mené notre propre expérience pour voir jusqu’où va une seule demande : La Vallée, un film 3D de 76 secondes avec un viaduc de pierre, un train à vapeur et un village, écrit par Claude Opus 5.5 dans un seul fichier HTML. On peut le regarder en vidéo ou l’ouvrir en direct dans le navigateur.

Cet article décrit ce que contient le fichier, comment chaque partie fonctionne, comment nous l’avons vérifié et le bug qui n’apparaissait que sur certains ordinateurs.

Ce que nous avons construit

Le film dure 76 secondes et compte six plans :

  1. La caméra sort de l’herbe sur un coteau avec des moutons, le titre apparaît.
  2. Plan large de la vallée vue du ciel. Le train arrive des collines de l’ouest avec un panache de fumée.
  3. Contre-plongée depuis la berge du canal : le train passe sur le viaduc au-dessus de la caméra.
  4. Travelling le long de la locomotive sur le viaduc.
  5. Vol le long du canal à travers le village, vers le viaduc.
  6. Mouvement de grue qui recule sur toute la vallée, avec le carton final.

Tout ce qui est à l’image vient du code : le relief, environ 2,08 millions de brins d’herbe, les arbres, les moutons, le viaduc, les rails et les traverses, le train et ses quatre voitures, des maisons aux toits de chaume, une église, des péniches, l’eau, la fumée, le ciel et les nuages. La bande-son est elle aussi synthétisée dans le navigateur. Le fichier compte 1 474 lignes. La seule bibliothèque est Three.js r185.

Pourquoi un seul fichier HTML

Un seul fichier offre des avantages concrets pour ce type de travail.

  • Il s’ouvre partout. Un double clic, un lien ou un dépôt sur n’importe quel hébergement statique suffit. Il n’y a ni étape de build ni serveur d’assets.
  • Le modèle voit tout le projet d’un coup. Claude lit la scène complète, modifie la caméra à un endroit et la fumée à un autre, et garde l’ensemble cohérent.
  • Chaque modification est un diff de texte. On peut la relire, l’annuler et la comparer aux versions précédentes.
  • Le chargement est léger. La page télécharge un petit fichier HTML et Three.js ; le reste est calculé sur la machine du visiteur.

Pour mmix.biz, une étape de plus a été nécessaire. La Content Security Policy du site n’autorise les scripts et les polices que depuis son propre domaine : Three.js et les deux polices sont donc stockés à côté du film et ne passent par aucun CDN.

Comment la scène est construite

Relief et voie ferrée

Le terrain est une carte de hauteurs de 3 sur 3 km issue d’un bruit simplex sur une grille de 750 sur 750. Un profil de vallée suit un canal sinueux, des collines s’élèvent de part et d’autre, et une couronne de montagnes en bruit de crêtes ferme l’horizon.

La voie ferrée est une spline qui traverse la vallée. Le long de celle-ci, le relief est ramené au niveau de la voie, ce qui crée remblais et tranchées. Là où le sol naturel descend de plus d’environ un mètre sous les rails, le code construit le viaduc : il mesure l’écart, le divise en arches égales et extrude un mur de pierre percé d’ouvertures en arc.

Deux millions de brins d’herbe

Un brin compte cinq sommets. La scène le dessine environ deux millions de fois par instanciation, et chaque copie porte sa position, sa rotation, sa hauteur, sa largeur et sa couleur. Le vent est calculé dans le vertex shader : un champ de bruit lent pour les rafales, un frémissement rapide propre à chaque brin et une courbure qui croît avec le carré de la hauteur le long du brin.

Le shader est intégré à un matériau Lambert standard de Three.js : l’herbe reçoit donc les mêmes ombres et le même brouillard que le reste. Un petit terme de contre-jour fait briller la pointe des brins quand la caméra regarde vers le soleil. L’herbe est placée sur un calque de rendu séparé que la passe de reflets de l’eau ignore, ce qui garde les reflets peu coûteux.

Lumière, brume et étalonnage

Le soleil est bas au nord-ouest, et la plupart des plans regardent vers la lumière. Nous avons remplacé le code de brouillard que Three.js injecte dans chaque matériau : la couleur du brouillard se réchauffe là où le rayon de vue pointe vers le soleil. Les crêtes lointaines proches du soleil deviennent dorées, celles de la direction opposée restent froides.

Une fois la scène dessinée, une passe de halo ajoute une lueur autour des zones claires, et une passe d’étalonnage finale ajoute une légère frange colorée sur les bords, un virage partiel des tons, un vignetage, du grain et des bandes cinéma au format 2,39:1.

Une caméra pilotée par une liste de plans

La caméra fonctionne comme une liste de plans. Chaque plan a une fenêtre de temps, un angle d’objectif, une zone d’ombres et une fonction qui renvoie la position de la caméra et le point visé. Les mouvements sont adoucis, une légère dérive « caméra à l’épaule » s’ajoute, et la caméra ne descend jamais sous le sol.

Le travelling est calculé à partir du train lui-même : la caméra tourne autour de la position actuelle de la locomotive sur les rails. La carte d’ombres suit chaque plan, et son centre s’aligne sur des texels entiers pour que les ombres ne scintillent pas pendant les mouvements de caméra.

Train, fumée et son sur une même horloge

La position du train est une fonction du temps du film : la distance parcourue le long de la voie à vitesse fixe. Chaque image est donc reproductible, ce qui compte pour l’export vidéo.

Les roues tournent de la distance divisée par le rayon. Chaque quart de tour des roues motrices envoie une bouffée de fumée par la cheminée et deux jets de vapeur par les cylindres. Le même événement joue un échappement dans la bande-son. Les particules de fumée ralentissent jusqu’à la vitesse du vent, grossissent et s’estompent en une dizaine de secondes.

Le son est construit avec WebAudio : bruit filtré pour les échappements, clics brefs aux joints de rail tous les 18 mètres, sifflet à trois voix, vent, chants d’oiseaux quand la caméra est proche du sol, et accords doux avec des notes de cloche à travers une réverbération générée. Le volume et la position stéréo du train suivent sa distance et sa direction par rapport à la caméra.

Comment nous avons vérifié

Chaque jugement sur le film s’est fait sur des images rendues. Le fichier a un mode capture : un paramètre d’URL choisit n’importe quel instant du film, et un petit crochet de script le rend exactement. Un Chromium sans fenêtre sur la station de travail du studio, avec accès à la carte graphique via ANGLE et Vulkan, a pris des images fixes de chaque plan.

La première relecture a trouvé des problèmes invisibles dans le code : des couches de brume qui rendaient la vallée laiteuse, des murs de maisons brûlés au blanc, des franges colorées trop fortes, un canal qui ressemblait à une rigole en béton et une fumée de cheminée posée sur les toits comme des boules de coton. Chaque série de corrections a été suivie de nouvelles images.

Ensuite, le film entier a été rendu : 2 280 images en 1920 sur 1080 à 30 images par seconde, en trois à quatre minutes environ. Une planche contact sur tout le film a vérifié le montage et le mouvement. En temps réel, la scène tient environ 60 images par seconde sur une RTX 3060.

Le bug que seuls certains ordinateurs voyaient

Après la première version, le fondateur du studio a signalé un clignotement noir au milieu du film. Notre vidéo ne contenait aucune image noire. La différence tenait au moteur graphique : nos tests tournaient sur Vulkan, et le clignotement apparaissait sur OpenGL.

Nous l’avons reproduit en lisant le film en temps réel sur le moteur OpenGL et en relevant des pixels à chaque image. À partir de la onzième seconde, plus de 1 000 images sur environ 4 600 étaient noires.

La cause tenait en une ligne d’arithmétique. Le rapport entre l’âge d’une particule de fumée et sa durée de vie pouvait dépasser légèrement 1 à sa dernière image. Élever un nombre négatif à une puissance fractionnaire renvoie NaN en JavaScript, et la particule recevait une taille et une transparence invalides. Sous OpenGL, cette particule dessinait quand même un pixel. La passe de halo étalait ensuite ce pixel invalide sur de grandes parties de l’image.

La correction borne le rapport à 1 et fait rejeter par le shader tout fragment dont la transparence échoue à une comparaison, ce qui attrape aussi NaN. La même mesure a ensuite montré zéro image noire. La leçon pratique : tester la lecture en temps réel sur plus d’un moteur graphique, car une capture hors ligne peut être propre alors qu’un navigateur en direct clignote.

Ce qu’il a fallu pour publier

Pour mettre le film sur ce site, nous avons :

  • rendu une version sans titres incrustés, pour qu’une seule vidéo serve aux cinq langues ;
  • encodé la vidéo en deux passes à environ 1,9 Mbit/s : 18 Mo, sous la limite de 25 Mo par fichier de Cloudflare Pages ;
  • créé une page en cinq langues avec des données structurées VideoObject et FAQ ;
  • ajouté la version 3D avec choix de langue et une herbe allégée pour les téléphones.

Quand choisir cette approche

Chaque outil a ses points forts.

  • Scène Three.js en un seul fichier. Une scène stylisée qui se charge vite sur un site, tourne en direct dans le navigateur et s’exporte en vidéo. Limites : rendu low-poly stylisé, pas de lancer de rayons de qualité cinéma, charge sensible sur les téléphones anciens.
  • Blender. Rendu photoréaliste, modélisation détaillée et vidéo hors ligne. Claude peut aussi piloter Blender via un serveur Model Context Protocol.
  • Unity ou Unreal. Grands mondes interactifs avec physique, outils d’animation et chaîne d’assets, pour des téléchargements plus lourds.

Pour une scène d’accueil de page produit, le survol d’un lieu, une bande-annonce d’événement ou une courte boucle pour les réseaux sociaux, une scène en un seul fichier suffit souvent. Nous réalisons ce type de travail dans le cadre de nos systèmes de contenu IA.

Le film, la vidéo et le lien vers la version 3D en direct se trouvent sur la page de l’expérience La Vallée.