WebGPU · from scratch · zéro dépendance de rendu

Une planète d'1,27 milliard de cellules.
Dans un onglet. En 1,5 s.

flux3d est un moteur 3D web orienté performance. Sa démo Hexacraft génère, streame et laisse terraformer une planète entière — voxels hexagonaux, rivières, 50 biomes, cavernes — sans jamais « charger » le monde.

init 1,5 s · JS 65 Mo · 1 268 776 962 cellules · 134 490 358 cavernes · 5 niveaux de LOD · édition < 100 ms · 10 suites de tests WebGPU headless · sauvegarde = diffs seuls · 50 biomes · hydrologie par priority-flood ·   init 1,5 s · JS 65 Mo · 1 268 776 962 cellules · 134 490 358 cavernes · 5 niveaux de LOD · édition < 100 ms · 10 suites de tests WebGPU headless · sauvegarde = diffs seuls · 50 biomes · hydrologie par priority-flood ·
0cellules adressables — aucune n'est stockée : le monde est une fonction
0de JavaScript résident, quelle que soit la taille de la planète
0entre l'ouverture de l'onglet et la planète à l'écran
0pour un coup de pinceau de terraforming massif (upload partiel ciblé)
0niveaux de LOD emboîtés ×4 (44 → 11 264), raccords sans couture
0biomes en 10 familles climatiques, dérivés de la température et de l'humidité
Idée fondatrice

Le monde n'est pas chargé. Il est calculé.

Tout l'état initial de la planète — relief, rivières, lacs, biomes, cavernes — est une fonction pure de la graine. Seules les éditions du joueur sont stockées (des « diffs » épars). Conséquences : mémoire indépendante de la taille du monde, sauvegardes minuscules, et un déterminisme total qui rend chaque bug reproductible au pixel près.

Graineun entier. C'est toute la « base de données ».
Macro-biomecontinents & aridité (fbm de bruit de gradient)
Macro-terrainmassifs + chaînes alpines (ridged)
Hydrologiepriority-flood : rivières, bassins, lacs — lits creusés
Détail fincôtes fractales, raidissement côtier monotone
BiomeT° (latitude, altitude) × humidité × relief → 1 des 50
Diffs joueurla seule chose sauvegardée — priorité absolue

VirtualGoldberg — la grille qui n'existe pas

La sphère est un pavage de Goldberg (hexagones + 12 pentagones) entièrement virtuel : indexOf, coordsOf, center, neighbors sont des formules, pas des tableaux. Passer d'une planète de 79 M à 1,27 Md de cellules ne coûte pas un octet de plus.

heightOf — O(1), appelé des millions de fois

Chaque requête traverse le pipeline hiérarchique puis un mémo direct-mapped de 16 384 entrées (~115 Ko) : pur, jamais invalidé — les diffs court-circuitent avant. Le localisateur de cellules est une marche gloutonne O(1) amorti sur le graphe de voisinage.

Multi-résolution

Cinq mondes emboîtés, un seul terrain

Une cascade de grilles ×4 (44 → 176 → 704 → 2 816 → 11 264). Le streamer descend l'arbre de tuiles triangulaires : il raffine selon la distance au bord de tuile pour les gros niveaux, au centre pour la promotion finale — avec hystérésis pour ne jamais clignoter. Le niveau 176 couvre la planète entière, épinglé : il n'y a jamais de trou.

Démo — la caméra (point clair) balaye le terrain : les tuiles se subdivisent ×4 près d'elle et se regroupent derrière, exactement comme le streamer descend(). L'anneau vert = hystérésis (on dé-raffine plus loin qu'on ne raffine).

Le fin n'est jamais trahi par le grossier

Les vues grossières échantillonnent 5 points du niveau fin (médiane robuste) : mêmes hauteurs, mêmes biomes, même plan d'eau — un lac garde exactement le même niveau à tous les LOD, vérifié par test. Les niveaux parents sont dessinés sous les feuilles (abaissés de 7 crans) pour boucher les coutures.

Pools LRU sous budget

Les niveaux fins ne vivent que dans des pools de slots GPU fixes (96 tuiles fines), générés à la demande, évincés en LRU, uploadés sous budget par frame. La demande est triée par distance : le plus proche d'abord, toujours.

Gestion mémoire

La mémoire ne croît pas avec le monde

Zéro tableau par cellule. Des structures SoA plates (typed arrays) pour tout ce qui est résident, des scratchs réutilisés à zéro allocation dans les chemins chauds, et un seul gros vertex buffer GPU à offsets fixes — l'anti-fragmentation par construction.

Monde procédural (1,27 Md cellules)
0 octet
Mémo terrain (direct-mapped)
~115 Ko
Hydrologie (SoA, grille 176)
~4 Mo
JS total résident
~65 Mo
GPU (pools + atlas + eau)
~2,3 Go

Sauvegarde = diffs

Exporter une planète terraformée n'écrit que les cellules éditées (Maps éparses → JSON). Un monde vierge : 0 octet de données.

Init < 2 s

La seule vraie construction à l'ouverture : l'hydrologie (~0,5 s, priority-flood sur 309 762 cellules, tas binaire plat) et l'échauffement du niveau planète-entière.

Textures procédurales

L'atlas de biomes (66 couches + mips complets) est généré au boot — aucun fichier image dans le projet. Fidèle au « from scratch ».

Mises à jour

Terraformer 10 000 cellules sans recharger une tuile

Chaque cellule possède son bloc de sommets à offset fixe dans le vertex buffer. Un coup de pinceau réécrit K blocs par writeBuffer ciblés — pas de rebuild de chunk, pas de latence. La nature (arbres, rochers, plantes) est un système d'entités instanciées : abattre un arbre retire une instance, le semis procédural rejouable fait le reste.

Démo — un pinceau circulaire édite des cellules : seules les cellules touchées (flash) sont ré-uploadées. Le compteur simule le coût réel : ~36 sommets par cellule modifiée, rien d'autre.

Streaming continu

~200 Mo/s de génération de tuiles pendant l'orbite, lissés sous budget par frame — la caméra ne bloque jamais.

Éditions en cascade

Creuser une fosse rabaisse automatiquement les vues parentes couvrantes (viewOver) : la sous-couche ne perce jamais dans l'excavation.

Cavernes creusables

134 M de poches procédurales (bande d'un bruit 3D) + éditions : percer un plafond, combler un tunnel — mêmes diffs, même sauvegarde.

Simulation

Des rivières qui descendent, des lacs qui affleurent, des climats qui se tiennent

Hydrologie dérivée, pas simulée

Un priority-flood (Barnes) comble les dépressions depuis la mer : chaque cellule connaît son exutoire — zéro plateau, zéro boucle. L'accumulation de flux trace 2 520 segments de rivières en 191 bassins versants ; les lits sont rendus monotones vers l'aval à l'init : chaque rivière descend, quel que soit le bruit fin. Le creusement s'applique dans heightOf : les vues LOD en héritent gratuitement.

Plans d'eau exacts

Chaque cellule d'eau douce connaît le rayon de son plan (lac − 0,5 cran, rivière lit + 0,4) : identique à tous les niveaux de détail, jamais percé par la sphère de mer — celle-ci est maillée avec une flèche de corde ≤ 0,1 cran, adaptée au rayon de la planète. Le tout est verrouillé par des tests dédiés.

Climat physique

Axe polaire perpendiculaire au plan solaire : l'insolation ne dépend que de la latitude. T° = f(cos lat) − 0,55 °C/cran d'altitude. Humidité = 1 − aridité (le même champ qui module la pluie). Le HUD affiche le biome et la température du point que vous survolez.

Mode carte

Un interrupteur bascule la planète en carte des biomes : 50 aplats couleur, géométrie aplatie, éclairage neutre — la face nuit aussi lisible que la face jour. Les chunks sont reconstruits avec les mêmes 9 flottants par sommet.

Ce qui le rend unique

Des choix qu'on ne fait nulle part ailleurs

🧮 Géométrie sphérique native

Pas de cubes-sphère, pas de projection : un vrai pavage de Goldberg. Le piéton marche sur la sphère, la gravité est radiale, les pôles sont des cellules comme les autres.

🔬 Testé comme un compilateur

10 suites Playwright pilotent un Chrome WebGPU headless : fidélité LOD au cran près, monotonie des rivières, invariants des plans d'eau, gradients climatiques, captures reproductibles par permalien (#az=…&el=…&r=…&sun=…).

⚡ WebGPU sans framework

Pipelines, WGSL, atlas, culling Hi-Z, tout est écrit à la main. Le harness du repo compare flux3d à three.js et Babylon sur les mêmes scènes.

🌍 Échelle sans compromis

×4 sur le rayon = une ligne de configuration. La cascade de LOD, la sphère d'eau, le streaming et les tests s'adaptent automatiquement — la taille des cellules, elle, ne bouge jamais (~1,8 m).

Essayer Hexacraft Ouvrir la carte des biomes Visualiseur IFC (même moteur)