Construire un monde ouvert dans le navigateur, partie 28 : de l'herbe jusqu'à l'horizon et un sol qui se masque lui-même
Par Oleg Sidorkin, CTO et cofondateur de Cinevva
Vous découvrez la série ? Consultez le guide de la série. Il explique ce qu'est un spike et renvoie vers toutes les parties.
La partie 27 a construit l'île et lui a donné un sol qui ne semble pas carrelé. Cette partie aborde les deux éléments qui donnent au terrain l'impression d'être habité plutôt que vide. Le Spike 56 porte sur l'herbe, ce détail de surface qui transforme une pente texturée en un lieu que l'on aurait envie de traverser, avec pour difficulté de faire en sorte qu'un champ ressemble bien à un champ plutôt qu'à des traits épars. Le Spike 57 fait l'inverse d'afficher davantage : il s'agit de ne pas afficher ce qu'une colline masque déjà, et le résultat intéressant est que la méthode rapide pour le déterminer s'est aussi révélée être la bonne.
Une herbe qui ressemble à un champ, pas à des confettis
Ouvrir le Spike 56 dans un nouvel onglet ↗ · Voir le code source
La décision fondamentale est géométrique. Une seule lame fine et effilée occupe moins d'un pixel sous la plupart des angles de caméra ; un demi-million de lames plates ressemblent donc à de rares confettis verts plutôt qu'à un champ. La solution est une touffe en quads croisés : trois quads effilés, espacés de soixante degrés autour de l'axe vertical local, de sorte que, quelle que soit la direction d'observation, au moins un quad soit presque perpendiculaire à la caméra et que chaque instance couvre à l'écran une surface réelle équivalant à environ trois largeurs de brin. C'est ce qui fait la différence entre des traits verts et de l'herbe.
Un noyau de calcul WebGPU positionne chaque touffe une seule fois à l'initialisation. Il hache l'indice de l'instance pour produire cinq flux aléatoires décorrélés, choisit une position XZ dans la parcelle, échantillonne la hauteur du sol à partir du même FBM que celui utilisé par le maillage du sol côté CPU — un portage TSL doté d'un modulo qui préserve le signe afin que les valeurs correspondent exactement et que les brins reposent sur la surface au lieu de flotter au-dessus —, calcule une normale par différences centrales, puis détermine aléatoirement la largeur, la hauteur et la teinte de chaque touffe. Côté rendu, un graphe de sommets TSL contourne entièrement la matrice d'instance et écrit directement dans l'espace de projection : il redimensionne le quad croisé unitaire, aligne l'axe vertical local sur la normale du sol grâce à la formule de Rodrigues, puis le translate vers la position de la touffe. Le LOD en fonction de la distance ne nécessite aucune passe d'élimination, car le graphe de sommets multiplie la hauteur de la touffe par
La recette des couleurs est empruntée au shader URP inspiré de Breath of the Wild de NedMakesGames : avec un ombrage plat, la couleur du brin est une interpolation entre une teinte à la racine et une teinte à la pointe selon la fraction de hauteur, ces deux teintes étant elles-mêmes interpolées entre deux palettes à partir de la valeur de teinte propre à chaque touffe. On obtient ainsi l'aspect bicolore moucheté d'un véritable champ d'herbe de BotW. L'éclairage diffus utilise la normale du sol orientée par rapport au soleil, avec un minimum ambiant, car les normales de chaque quad croisé produisent trop de bruit pour être ombrées individuellement dans un rendu stylisé. Tout le champ est rendu en un seul appel de dessin, entièrement positionné et animé sur le GPU.
Quatre façons d'éliminer ce qu'une colline masque
Ouvrir le Spike 57 dans un nouvel onglet ↗ · Voir le code source
Le Spike 57 compare quatre méthodes d'élimination sur le même monde procédural diffusé en streaming par le client de production, avec une échelle verticale multipliée par 1,8 afin que les collines masquent réellement la végétation. T0 se limite à la distance, comme le fait déjà le système de visibilité des chunks en production. T1 ajoute l'élimination par frustum, le gain peu coûteux le plus important, en supprimant tout ce qui se trouve en dehors du cône de vision. T2 ajoute un test d'horizon tenant compte du terrain : un rayon est parcouru depuis l'œil jusqu'à chaque instance, qui est rejetée si la heightmap s'élève au-dessus du rayon à un point quelconque du trajet. Un arbre derrière une crête est ainsi éliminé même s'il se trouve dans le frustum. T3 conserve le même test d'horizon, mais l'accélère avec une pyramide de hauteurs maximales. T4 porte l'ensemble du test distance-frustum-horizon dans un noyau de calcul TSL, qui écrit pour chaque instance un facteur de visibilité lu par le matériau de la végétation afin de réduire à zéro les sommets masqués. Un compteur de visibilité persistante sur deux images atténue le scintillement d'une seule image lorsqu'un point d'échantillonnage passe juste à l'intérieur ou à l'extérieur d'un texel au moindre mouvement de la caméra. Cette durée reste volontairement courte, car une valeur plus longue masquerait les erreurs algorithmiques au lieu de les corriger.
C'est avec la pyramide que le spike prend tout son sens, et la leçon consiste à faire correspondre le test à ce qui apparaît réellement à l'écran. Le terrain rendu est un maillage triangulaire dont les sommets sont placés sur une grille fixe de deux mètres. Entre les sommets, le rastériseur effectue une interpolation linéaire ; la hauteur réellement affichée à l'intérieur d'un rectangle est donc le maximum des sommets qu'il contient, jamais le pic du bruit continu situé entre eux. Si la pyramide d'occlusion échantillonne le bruit sur une grille plus fine, elle détecte des pics fantômes que le maillage n'affiche jamais et commence à bloquer des rayons dont la caméra voit pourtant clairement le trajet. Les texels de base de la pyramide sont donc placés exactement sur la grille des sommets, chacun stockant le maximum de ses quatre sommets d'angle, tandis que les niveaux supérieurs emploient des réductions maximales 2x2 classiques. La pyramide est ainsi exacte par rapport au maillage rendu. Pour le test du rayon à chaque étape, le code échantillonne délibérément le maillage par interpolation bilinéaire au lieu d'interroger la pyramide, car une requête AABB plus petite qu'un texel renvoie le maximum de l'ensemble du texel et augmente artificiellement la hauteur de plusieurs mètres sur les crêtes abruptes, provoquant précisément la sur-occlusion qui masquerait des éléments pourtant visibles.
Le résultat surprenant est que T2, la référence par force brute, est la méthode erronée. Comme T2 échantillonne directement le bruit continu en un point, elle détecte entre les sommets du maillage des pics qui ne sont jamais rendus. Elle produit donc une légère sur-occlusion et masque de la végétation que le joueur peut réellement voir. La méthode pyramidale est à la fois plus rapide, grâce à la réduction AABB en
Technologies abordées dans ce chapitre
Herbe GPU en quads croisés. Trois quads effilés, espacés de soixante degrés par touffe, garantissent qu'au moins l'un d'eux sera presque perpendiculaire à la caméra sous n'importe quel angle. Un demi-million d'instances ressemblent ainsi à un champ plutôt qu'à des confettis de moins d'un pixel. Un noyau de calcul positionne chaque touffe — hauteur du sol FBM échantillonnée avec le même modulo préservant le signe que le maillage CPU, normale par différences centrales, taille et teinte propres à chaque touffe —, tandis qu'un graphe de sommets TSL contourne la matrice d'instance pour redimensionner la touffe, l'aligner sur la normale par rotation de Rodrigues, la translater et lui appliquer un mouvement de vent modulé par la hauteur. Le LOD en fonction de la distance est gratuit : les touffes s'aplatissent jusqu'à une hauteur nulle selon
Élimination par occlusion de l'horizon du terrain. Quatre méthodes sont comparées sur le monde de production : distance, puis frustum, puis un test de rayon sur la heightmap qui rejette les instances situées derrière une crête, puis une pyramide de hauteurs maximales qui accélère ce test, et enfin un portage en calcul TSL. La pyramide échantillonne exactement sur la grille de sommets de deux mètres utilisée pour la tessellation du maillage — texel de base égal au maximum des quatre sommets d'angle, puis réductions maximales 2x2 vers le haut —, de sorte qu'elle ne renvoie que les hauteurs réellement affichées par le rastériseur.
Accélérée et juste, sans compromis. L'échantillonnage ponctuel du bruit continu — la méthode T2 par force brute — détecte entre les sommets du maillage des pics qui ne sont jamais rendus, ce qui produit une sur-occlusion de la végétation visible. La pyramide alignée sur la grille des sommets est à la fois plus rapide — réduction AABB en
Partie 28 sur 29. Précédent : Partie 27 — Une île issue du bruit, avec un sol qui ressemble à un sol Suivant : Partie 29 — Un seul contrôleur, n'importe quel corps Guide de la série : /fr/blog/2026-02-25-open-world-browser-series-guide