voxelforge

Un moteur voxel avec une démo jouable dans le navigateur. Le renderer vise WebGL2/WASM, tandis que le coeur de simulation se compile en natif et est couvert par des tests - des dizaines de milliers d'assertions.

voxelforge
TL;DR

Un moteur voxel avec une démo jouable dans le navigateur. L'astuce est que le cœur de simulation ne sait rien du rendu - ce qui permet de tester la logique sans GPU, à travers des dizaines de milliers d'assertions.

Aperçu

voxelforge est un moteur voxel avec une démo jouable qui tourne dans le navigateur. Le moteur de rendu vise WebGL2 et WASM, mais la décision la plus intéressante ne concerne pas le graphisme, mais l'architecture : le cœur de simulation est totalement coupé du rendu. C'est lui qui détient les voxels, les règles et les voisinages, et il ne sait rien de ce qui apparaît à l'écran.

Cette seule décision a changé la nature du projet. Au lieu d'un moteur qui ne fonctionne que si on le lance avec une carte graphique, il est devenu une bibliothèque de logique qui tourne partout et se teste comme du code ordinaire. Le reste de cette étude de cas raconte pourquoi cela a payé.

Un moteur voxel doit faire deux choses difficiles en même temps : dessiner le monde vite et le simuler correctement. Les deux sont faciles à casser d'une façon qui paraît bonne au premier coup d'œil et qui pourtant est fausse - un bloc disparaît une image trop tard, un voisinage est compté un voxel à côté. Ces erreurs ne crient pas, elles cassent le monde en silence.

Quand le rendu et la logique sont tressés dans un même corps de code, on ne peut les séparer ni pour les tests ni pour le débogage. On ne peut pas dire si un bloc a mal disparu parce que la simulation l'a mal calculé, ou parce que le moteur de rendu l'a mal dessiné. Démêler ces deux mondes fut la chose la plus importante de tout le projet.

Un cœur qui ne connaît pas le GPU

La solution était aussi la plus simple : le cœur de simulation est de la logique pure, et le moteur de rendu prend son état et le transforme en triangles. Aucune partie du cœur ne touche à un canvas ni à un GPU. L'interface entre eux est étroite et explicite, donc le moteur de rendu peut être quelconque, et le cœur n'en sait rien.

core.ts · typescript
interface SimulationCore {
  tick(dt: number): void;
  voxelAt(x: number, y: number, z: number): Voxel;
}

interface Renderer {
  draw(core: SimulationCore): void;
}

Qui fait quoi

CoucheRôleDépendance au GPU
Cœur de simulationvoxels, règles, voisinagesaucune
Moteur de rendutransformer l'état en trianglesWebGL2 / WASM
i
À noter

Comme le cœur ne dépend pas d'un GPU, il est construit nativement et testé comme une bibliothèque normale. Le moteur de rendu vise WebGL2 et WASM, mais la logique passe ses tests même sur une machine de CI sans carte graphique.

Des tests plutôt que de l'espoir

Cette séparation n'est pas un luxe académique. C'est pourquoi la simulation a une couverture de tests de l'ordre de dizaines de milliers d'assertions - et c'est le seul moyen de dire qu'un moteur voxel est correct, et pas seulement qu'il "paraît bon". Les erreurs d'un voxel à côté surgissent dans un test, pas après une heure de jeu.

milliers
voxels par chunk
dizaines de milliers
assertions dans les tests du cœur
0
dépendances du cœur au GPU

Le résultat : une démo qui grandit sans peur

Ce qui en sort est une démo jouable dans le navigateur qui peut grandir sans craindre de casser en silence la logique du monde au passage. Parce que le cœur est testé à part, un changement dans le moteur de rendu ne peut pas casser la simulation en douce, et un changement dans la simulation surgit aussitôt dans les assertions. Le moteur n'est pas seulement spectaculaire - il est vérifiable.

Plus de projets

D'autres réalisations de la même catégorie - découvrez comment nous abordons des défis similaires.

Vous avez un projet similaire ?

Contactez-nous - le devis est gratuit et arrive sous une heure.