Herbe & Végétation


Bonjour à tous,

Récemment, j’ai essayé d’améliorer la démo visuellement pour que le jeu ait un meilleur look. J’ai pas mal travaillé sur le rendu de l’herbe et de la végétation notamment, et c’est ce que je vais détailler dans cet article.

20170810_121404

Hop, un nouveau système de végétation.

 

I – Le système d’herbe de Unity

Avant tout, j’ai envisagé d’utiliser le système de terrain et de végétation de Unity, mais j’ai été confronté à 2 problèmes:

Tout d’abord, les terrains de mon jeu sont assez complexes, avec des îles volantes, des cavernes, des trous, des ponts, et autres formes non convexes. Unity propose uniquement des terrains de type « height map », ce qui ne permet pas de générer de l’herbe sur tous les côtés et au-dessous d’une île volante par exemple.

Ensuite, le système de végétation de Unity est conçu pour gérer l’affichage de l’herbe sur des terrains immenses. Le batching est donc en grande partie dynamique. Cela génère beaucoup de draw calls (sur le peu de test que j’ai faits), et ça ralentit pas mal le jeu.

Voilà pourquoi j’ai choisi de créer mon propre système de végétation pour le jeu.

 

II – Le nouveau système de végétation

L’idée principale derrière ce choix est de pouvoir créer facilement des champs d’herbe en quelques clics, tout en gardant un bon contrôle sur la partie artistique. J’utilise Blender comme outil pour le level design (entre autres), donc je dois trouver un moyen d’exporter l’herbe et les réglages divers vers Unity via le format FBX. Je souhaite avoir quelque chose d’assez léger en taille de fichier et qui puisse s’adapter facilement aux différents cas d’utilisation que je vais rencontrer (végétation à la verticale sur les murs, ou mousse dessous les îles volantes, …). Voici ce à quoi j’ai abouti:

Dans Blender

Pour les raisons évoquées ci-dessus, j’ai choisi d’utiliser les couleurs associées à chaque sommet sur des maillages/meshes faits à la main. Ca me permet de créer ces fameux meshes uniquement à l’endroit où je souhaite avoir de la végétation. En outre, je peux utiliser les 3 canaux de couleurs pour créer 3 types de végétation différents sur un même mesh. Pour peindre facilement chaque canal, j’utilise les brosses « Add » et « Sub » de Blender avec des couleurs rouge, bleue et verte pures.

Bien sûr, j’utilise un nom spécial sur ce mesh avec des conventions spécifiques pour signaler à Unity le type de végétation que je désire.

Je peux superposer plusieurs meshes les uns sur les autres, donc il n’y a virtuellement pas de limite au nombre de végétations différentes que le système peut gérer.

20170816_vertexColorGrass

Voici le mesh avec les couleurs de sommets dans Blender. Pour ce mesh, j’utilise le rouge pour l’herbe, le vert pour la mousse, et le bleu pour des sortes de lianes tombantes.

Bien sûr, c’est un peu déroutant de « peindre » l’herbe sans réellement la voir dans Blender (l’herbe réelle est générée plus tard dans Unity). Mais c’est le prix à payer pour avoir des fichiers d’export assez légers. Et puis… on finit par s’habituer :)

20170816_vertexColorRocks

Si je ne veux pas d’herbe partout, je peux juste créer un petit mesh à l’endroit spécifique qui m’intéresse. C’est très léger lorsqu’on exporte en FBX.

 

Dans Unity

Ensuite, lorsque j’importe le niveau dans Unity, mes scripts d’import vont générer la végétation avec une densité fonction de l’intensité de couleur des sommets du mesh. Chaque élément de végétation est généré à partir d’un prefab. Le prefab est automatiquement « collé » et orienté de manière adéquate sur la 1ère surface viable sous-jacente. Bien sûr définir une surface « viable » n’est pas aussi simple que ça (je dois tester le type de surface…), mais vous avez saisi l’idée.

20170810_154114

Parfois, le « collage » automatique de l’herbe sur les surfaces amène de curieux résultats (l’herbe sur le panneau ici, ce qui est plutôt rigolo, mais pas voulu). J’ai donc du mettre en place plusieurs règles spécifiques pour empêcher ce genre de choses, ou, tout du moins, les contrôler.

J’ai également mis en place une étape de randomisation, qui me permet de changer de manière aléatoire la taille, la rotation ou ce que j’estime nécessaire sur chaque prefab généré. Ceci permet de créer plus de variations.

20170810_174518

Une capture d’écran présentant les 3 types de végétation: de l’herbe au premier plan, de la mousse sur les parois verticales, et des lianes tombantes dessous.

20170811_102213

Une autre image de la Guilde des Voleurs avec beaucoup d’herbe.

Ensuite, une fois que tous les prefabs ont été générés, je les fusionne (« batche ») tous par matériau. Tout est rassemblé dans des meshes de ~65000 sommets, qui est la limite imposée par Unity. Evidemment, cela résulte en plusieurs meshes « batchés » (généralement autour de 50, mais on peut monter à plus que ça). Cela réduit considérablement le nombre de draw calls.

III – Pour & Contre

Comme d’habitude, cette approche a de bons et de mauvais côtés:

Le batching statique de tous les meshes d’herbe tel que je le fais empêche d’avoir un affichage dynamique permettant de montrer ou de cacher les brins d’herbe en fonction de la distance, car tout est batché dans un ordre aléatoire. Cela signifie que chaque brin d’herbe sur une île est visible de n’importe où sur cette même île. Mais comme les îles de mon jeu sont relativement petites, ça a l’air OK pour l’instant. A l’avenir, si je devais optimiser encore, je pourrai toujours introduire une structure de type octree pour segmenter l’herbe par région et/ou utiliser un shader intelligent qui pourrait « clipper » la geométrie lointaine.

Par contre, le batching statique avec ordre aléatoire a un avantage: je peux choisir de n’activer que la moitié des meshes de végétation, et cela divise la densité de l’herbe par 2 partout de manière uniforme. Afficher de l’herbe reste un processus assez coûteux pour la carte graphique, et il est bien pratique de pouvoir dynamiquement diminuer la densité de l’herbe pour faire tourner le jeu sur des configurations plus modestes.

Une autre bonne nouvelle est que, comme l’herbe est générée dynamiquement via des prefabs, ce système de végétation sait en réalité gérer les prefabs d’une manière générale, et pas uniquement la végétation; donc des rochers aussi par exemple. Je devrais donc plutôt l’appeler « système de génération de détails » en fait.

20170816_222620

Quelques rochers générés avec le nouveau système de génération de détails.

Un autre avantage est que je peux également positionner manuellement les prefabs d’herbe si je le souhaite. Ils bénéficieront également du système de batching. Je peux donc utiliser le système de génération de végétation pour les larges zones et faire du placement manuel pour les zones plus petites, ou plus spécifiques.

 

20170816_232045

Quelques herbes positionnées manuellement sur les rochers.

20170816_231738

Une petite grotte avec beaucoup de lianes…

IV – Performances

Pour l’instant, le jeu affiche 80 000 éléments de végétations avec une fréquence d’affichage correcte (~30 fps) sur une configuration moyenne. Bien sûr cela dépend du nombre de polygones sur chaque prefab. Il faut donc être très pointilleux lors de la modélisation de chaque élément de végétation.

Et comme j’avais déjà codé des shaders spécifiques pour la végétation, je peux les réutiliser pour ce nouveau système. Du coup, l’herbe réagit toujours au vent et au déplacement du personnage.

20170810_180233

Voilà, c’est tout pour aujourd’hui! J’espère que ce n’était pas trop technique. Ce système de génération de végétation est encore tout récent, donc j’espère pouvoir l’affiner dans les prochains mois pour le rendre plus efficace, et plus adapté aux problèmes que soulève le jeu.

A+!

Paix!

 


Abonnez-vous par mail pour ne rien rater de l'actu !

Soutenez-moi sur Tipeee
Démo & Info: www.oneiricworlds.com
Suivez-moi: Facebook, Twitter, Google+, IndieDB, Steam Greenlight


Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *