Je suis Overdrivr, 23 ans, et je viens présenter un module que je programme pour le moteur de jeu Nazara, dévellopé par Lynix. Nazara se veut facile d'accès et puissant d'utilisation, et c'est également dans cet esprit que je développe Dynaterrain.
J'ai aussi contribué à ce moteur avec un module de génération de bruits, et je me remet le couvert pour un terrain dynamique et infini. Je le précise car NzNoise sera utilisé dans DynaTerrain pour générer des terrains de manière procédurale.
Dynaterrain ?
DynaTerrain est un moteur de terrain infini, codé en C++. Mon but est de fournir à l'utilisateur un système avancé de terrain, capable de gérer des espaces bien plus importants que les terrains classiques.
Pour cela, le système est basé sur deux techniques :
Un maillage du terrain qui s'adapte en temps réel
L'utilisation d'algorithmes de génération procédurale (néanmoins combinés aux heightmaps classiques) pour générer automatiquement les reliefs
Là où un terrain classique pourra gérer au grand maximum quelques dizaines de km², DynaTerrain devrait être capable de gérer des étendues immenses avec une résolution locale d'un mètre. Cela est possible par l'utilisation d'un maillage dynamique qui est mis à jour en temps réel de manière à être précis seulement là où c'est nécessaire (globalement autour de la caméra).
Comment l'utiliser ?
De par sa nature, ce module s'adresse à deux métiers :
L'artiste
Le programmeur
Programmeur
En tant que programmeur, il vous faut réaliser quelques actions :
Hériter la classe NzHeightSource, puis réimplémenter sa méthode ::GetProceduralHeight(float x, float y). Dans cette méthode, libre à vous de mettre ce que vous voulez. Si vous souhaitez que votre terrain soit plat, un "return 0.f" suffit. Si vous souhaitez créer un terrain en forme de sinusoide, un simple "return std::sin(x)" suffit également.
Il est également possible d'utiliser mon module de bruits NzNoise, le bruit NzHybridMultiFractal2D produit naturellement des terrains très réalistes.
Il vous faut ensuite simplement instancier la classe NzTerrainQuadtree en lui passant votre classe héritée de NzHeightSource.
Et enfin, il est nécessaire d'appeller dans la boucle principale les fonctions NzQuadtree::Update(cameraPosition) et NzQuadtree::Render.
C'est le minimum requis, il est néanmoins possible de faire bien plus, ce qui sera détaillé dans un tutoriel.
Artiste
L'artiste est nécessaire si vous souhaitez modifier manuellement certaines parties du terrain. Dans ce cas, le programmeur pourra exporter, par une fonction du module de terrain, une heightmap de la zone désirée. Libre à vous de modifier cette carte avec votre logiciel de dessin favori.
Une fois les modifications faites, il suffit de retourner la heightmap à DT via une autre fonction, qui l'optimisera et la mettra en forme pour son usage interne.
C'est une façon de faire un peu "rustique" je vous l'accorde, mais l'implémentation d'un éditeur qui facilitera la tâche est au programme.
Démo
Note : Cette démo commence déjà à dater, une nouvelle est en préparation
Un point important sur la démo, c'est toujours une version expérimentale. Les performances et le rendu de l'image n'ont pas été ma priorité, cette démo fait la présentation de la logique derrière le module. Niveaux performances, aucun culling n'est pour l'instant implémenté, ce qui peut causer des baisses de FPS sur les GPU un peu anciens. Dynaterrain par contre ne devrait pas trop endommager le framerate, car il a une certaine durée allouée par frame pour faire son boulot.
Features
Voici la liste des fonctionnalités, avec en vert celles implémentées et fonctionnelles :
Précision variable du terrain en fonction de la pente
LOD "distance à la caméra"
LOD "screen space error"
Réduction de la précision à l'éloignement de la caméra
Gestion des transitions entre 2 niveaux différents de précision
Je suivais déjà ça sur l'autre thread. La technologie est intéressante, est-ce que c'est prévu de fournir une sorte d'éditeur de terrain à partir de ça pour pouvoir exporter un terrain dans un moteur de jeu classique, sous forme de mesh (OBJ, FBX, etc) ?
L'éditeur de terrain est bien prévu, par contre l'exporteur, tout dépend de comment je vais stocker les données manuelles du terrain. Si je pars sur des chunks de heightmap, exporter sous forme de mesh va demander un peu de boulot je pense.
Quelque chose de plus simple pour moi serait d'exporter le terrain sous forme de heightmap. En plus, ça serait plus flexible (zones non carrées, choix de la précision, etc). Reste à voir si le moteur de jeu est capable de générer des terrains avec ça, non pas que ça soit compliqué, mais c'est juste un peu vieux comme technique.
Justement, ce que je trouve intéressant ici c'est le mécanisme de génération "naturelle" + la tessellation automatique suivant le relief. Si on pouvait à partir de ça, exporter des chunks carrés, uvmappés avec des bordures tilables, dans un format classique (ne serait-ce qu'un truc trivial comme ASE) ça serait franchement intéressant. La gestion des terrains est vite pénible dans les moteurs de jeu...
Ah si avoir un ensemble de chunks ne te gène pas, c'est relativement simple. Niveau texture mapping, c'est nettement mieux de le faire en triplanar procéduralement dans le shader, plutôt qu'avec des uv, mais c'est également très simple à rajouter.
Je regarderais ça dés que j'aurais tombé le prochain point important de ma todo list.
Par contre le lien donné est invalide, tu as interverti le texte et l'URL.
Sinon pour l'exportation du terrain, je pense que le plus simple serait d'intégrer la fonctionnalité dans DynaTerrain (Exportation sous forme de Mesh pour bénéficier de l'enregistrement de ressources de Nazara).
Et pourquoi pas faire un outil graphique à côté permettant d'utiliser ça de façon simple
Ce site commence un peu à me fatiguer... A nouveau, je ne peux plus modifier le premier post. Je vais signaler le bug mais là c'est franchement pénible.
Sinon oui, dés que la gui seras intégrée dans Nz, je vais avoir pas mal de choses à rajouter !
Un petit up pour dire qu'il est désormais possible de régler de manière globale la taille des cercles de précision autour de la caméra. En spécifiant simplement la taille du plus petit cercle, c'est à dire le cercle dans lequel la précision est maximale, ainsi que le rapport des rayons de deux cercles consécutifs, il est possible de gérer assez grossièrement l'augmentation du nombre de triangles généré par la caméra.
Un point sympathique, le fait d'augmenter le nombre de rayons n'affecte absolument pas la rapidité de l'algorithme, qui n'effectue qu'une traversée partielle de l'arbre. En d'autres termes, les performances sont toujours au rendez-vous !
J'ai désormais le champ libre pour ajouter de nouvelles fonctionnalités. En tête de liste, la possibilité de lier des quadtree ensemble pour créer un terrain infini !
La liaison de quadtree est operationnelle ! Ca a pris moins de temps que prévu, c'est un changement vraiment bienvenu
Place aux images :
Les quadtree sont obligatoirement carrés, mais en les liant ensemble on gagne en liberté. Et comme vous pouvez le constater, le mesh global est toujours bien continu aux interfaces entre les deux quatrees, pas le moindre trou :
@charlesfire : merci ! Je pense que Lynix apprécie également !
J'en profites pour communiquer les dernières news toutes fraiches. J'ai mis en ligne un commit assez gros, j'essayerais d'éviter ça à l'avenir, mais passons.
Concrètement, l'architecture quasi "finale" du module est en place. Niveau code, il n'y a pas des masses de différences avant la mise à jour, par contre niveau fonctionnalité il y a une belle surprise :
Hé oui, les planètes font leur entrée ! Sur les deux images précédentes, seulement deux parmi les 6 quadtree nécessaires ont été mis en place, je rajouterais les 4 autres dans le prochain commit pour avoir une planète complète.
Un point important, le terrain et la planète utilisent la même classe de quadtree et de node (qui constituent véritablement le coeur du module), ce qui veut dire que la moindre optimisation ou amélioration faite sur ces classes impactera positivement à la fois sur le terrain et la planète. Et pour vous utilisateurs, ça signifie que les interfaces pour utiliser un terrain et une planète sont quasi-identiques, donc rien à apprendre en plus !
Maintenant que cette fonctionnalité est en place, je vais me consacrer à interfacer le terrain/planète avec le manager de scène développé par Lynix. Une fois ça de fait, le module pourra profiter de toutes les fonctionnalités du manager de scène, à savoir principalement le culling et l'éclairage.
Parce qu'il serait idiot d'éclairer un mesh avec une texture de débug, si quelqu'un de doué sous photoshop/gimp/whatever avait la motivation de réaliser une vraie texture de terrain pour ce projet, ça serait chouette, car c'est bien en dehors de mes compétences. Juste pour note, la texture totale doit avoir une taille de 2048*2048px et comporter 16 tiles de 512*512px chacune.
Salut et déjà felicitation pour ton module, toussa toussa
Un des points m'a fait réagir, je te cite :
>L'artiste est nécessaire si vous souhaitez modifier manuellement certaines parties du terrain. Dans ce cas, le programmeur pourra exporter, par une fonction du module de terrain, une heightmap de la zone désirée. Libre à vous de modifier cette carte avec votre logiciel de dessin favori.
>Une fois les modifications faites, il suffit de retourner la heightmap à DT via une autre fonction, qui l'optimisera et la mettra en forme pour son usage interne.
>C'est une façon de faire un peu "rustique" je vous l'accorde, mais l'implémentation d'un éditeur qui facilitera la tâche est au programme.
Je comprend la logique, probablement le plus simple à implémenter, mais je trouve ça dommage...
Déjà tout ça suppose que ton module de gestion de terrain soit capable de gérer les terrains mixtes. Mais je ne comprend pas pourquoi on ne semble pas pouvoir directement manipuler la forme interne.
Image un exemple tout bete. Je fais un jeux de strategie/gestion/god-mod. Il y a bien des cas où editer le terrain directement dans le jeux est necessaire. Pense a Sim-city par ex. Donc ce serait bien que l'on puisse modifier directement depuis le moteur certaines portions du terrain sans faire un export en heightmap en mémoire, modifier la heightmap et lui demander de reprendre la nouvelle...
Enfin concernant l'interne justement, comment compte tu l'implementer ? Si j'ai bien compris tu a un maillage de quad-tree et chacun sera soit basé sur une fonction math (genre bruit), soit une height map. Ce serait bien d'envisager un modèle "mixte". Pour certains cas l'artiste va faire des grosses modifs sur le relief. Dans ces cas là un quadtree purrement basé maillage est probablement mieux. Mais dans certains cas ce ne sera que de petits ajustements. Pour reprendre mon ex du jeux de stratégie, imagine que je veux faire un jeu où le terrain est déformé par les impacts d'obus. Quand je vais vouloir appliquer ça, dans l'etat actuel, je suis obligé de transformer toute la zone en height-map pour appliquer une microdeformation local. Il serait beaucoup plus efficace dans ces cas là d'avoir un "layer" de deformation par dessus celui généré par le bruit. Un truc qui, dans mon cas, ne renverra une modif qu'autour de l'impact. Dans l'idée c'est le meme principe que les algos de compressions video par ex. On encode regulièrement une trame complete (image) mais par ex la suivante ne contient que la différence vis a vis de la precedente. Et comme dans la majorité des cas les différences sont minimes, il y a beaucoup moins de données à traiter, on peut compresser ça fortement car "plein de zero".
Apres il est possible que je n'ai pas totalement compris comment tu comptais implementer ça !
Très bonne remarque, pour être honnête je n'ai pas encore eu le temps de trop bosser sur toute la partie "édition du terrain". Néanmoins l'édition directe est prévue, et il n'y a pas tant de choses à implémenter que ça car le principal élément, le maillage dynamique, fonctionne déjà. Je suppose qu'il suffira de forcer la maj de certains patchs pour avoir déjà quelque chose de fonctionnel. Niveau interfaces, un système de brosses devrait faire le travail correctement.
Sinon en interne, j'ai prévu que les heightmaps fournies par l'utilisateur soient découpées en chunks plus petits de taille fixe, de manière à justement réduire l'espace occupé. Mais il est vrai que pour des déformations mineures ton idée est très bonne, je la note.
Si j'ai bien compris tu a un maillage de quad-tree et chacun sera soit basé sur une fonction math (genre bruit), soit une height map. Ce serait bien d'envisager un modèle "mixte". Pour certains cas l'artiste va faire des grosses modifs sur le relief. Dans ces cas là un quadtree purrement basé maillage est probablement mieux.
En fait, que les données de hauteur soient procédurales ou manuelles, le quadtree n'y voit que du feu. Dans tout les cas, le quadtree gère des nodes, dont chacun possède son maillage. Le fonctionnement du module est assez obscur sans regarder longuement le code, c'est pourquoi je suis en train d'écrire un petit guide qui explique l'utilisation et le fonctionnement interne.
Avant de la mettre en ligne, j'aimerais remplacer les vertex buffers actuels par des buffers hybrides, qui devraient normalement éliminer les longs temps d'attente de quelques ms qui apparaissent parfois lorsque programme écrit sur un vertex buffer en même temps que le GPU bosse dessus. Non seulement ça permettra de gagner pas mal en perfs, mais en plus ça éliminera les chutes de framerates qui sont désagréables.
J'aurais bien aimé aussi remplacer les textures de test par des réelles, mais personne ne s'est encore montré intéressé, j'ai pas trop relancé non plus il faut dire.
L'éclairage c'était prévu, mais ça attendra je pense.
Vu que j'ai pas trop de temps libre en ce moment, et qu'il faut implémenter le buffer hybride et mettre en place les modifs, il faut compter 1 à 2 semaines (comprendre donc 2 à 3).
Aussi il serait possible que tu fasse une 'texture' sur la hauteur de la map en dégradé (blanc -> gris -> marron -> vert (montagne puis terre et herbe)), pour les tests
Déjà j'ai remis en place la distribution des tâches du terrain qui fonctionnait partiellement, et désormais normalement grâce à quelques modifications... La conséquence : quoi qu'il arrive, le framerate est fixé et le terrain ne provoque aucune baisse. Avant j'observais parfois des baisses, désormais c'est parfaitement stable.
Vu que les perfs sont de retour, je vais préparer immédiatement la démo qui inclueras à la fois un terrain plat et une planète (une toute petite lune pour l'instant disons). Je m'intéresse de près à l'éclairage désormais, et j'implémenterais un frustum culling juste avant.
Merci beaucoup, en fait c'est plutôt infinty : the quest for earth qui m'a donné envie de faire ce genre de choses, mais c'est vrai qu'Outerra est très impressionnant également, graphismes très réalistes...
En ce moment peu de nouveautés au niveau "rendu", l'éclairage demande de retravailler certains points de Nazara, ce qu'on verra avec Lynix dans quelques temps. En attendant j'améliore l'intégration du terrain avec le système de nodes du manager de scène de Nazara, le terrain peut désormais être déplacé/tourné/redimensionné en temps réel. Je m'attelle à la démo juste après.
Je retravaille actuellement le fonctionnement interne du module, rien de bien méchant mais c'est un peu ingrat, pas d'amélioration niveau rendu... Je suis aussi en train de terminer les planètes, quelques petits problèmes de connexion mais rien d'insoluble. Ensuite place aux terrains infinis, et surtout avant ça, la démo.
Il y a toujours pas mal de boulot à faire (modification par heightmap, modif en temps réel, morphing, éclairage) et des optimisations aussi avant d'avoir un truc vraiment fonctionnel, mais ça avance quand même.
Pour vous faire patienter (c'est d'ailleurs un example typique de "parfois 3 lignes de codes améliorent bien plus le rendu que 100 un autre fois") :
Dynaterrain avait besoin d'un bon coup de nettoyage, le module devenait trop complexe, quasi-impossible à maintenir et le code était globalement illisible. En m'inspirant du renderer de Nazara, j'ai séparé le module en deux :
Dynaterrain, dont le rôle est désormais, à partir de quelques infos (position de la caméra, paramètres) de générer et mettre à jour le maillage stocké dans une structure de donnée adaptée, nommée terrainChunk, ainsi que d'offrir à l'utilisateur une interface pour afficher, modifier et faire d'autres choses avec le terrain. Il tire toujours partit de l'efficacité d'un quadtree pour son optimisation interne.
TerrainRenderer, le nouveau module, fournit un renderer capable en un seul appel de dessiner un terrainChunk. Il défini aussi la structure de données terrainChunk, ainsi que diverses classes nécessaires au fonctionnement interne de terrainChunk.
En gros, j'ai séparé la logique du rendu. Pour l'instant le module ne compile pas, le temps de faire toutes les modifications nécessaires. Une fois ça de fait, ça permettra de repartir sur des bases saines pour la suite.
Je suis avec intérêt ton projet, tout ça me paraît très poussé (quadtree & cie, c'est du lourd ). As-tu une idée en tête de ce que tu va en faire, une application qui te tiendrait à coeur?
Bonjour OveRdrivR et content de voir des nouvelles de DynaTerrain!
J'ai cependant quelques questions quant à la séparation en deux modules:
Quelles sont les dépendances entre les modules (si j'ai bien compris DynaTerrain ne génère qu'une structure mais ne permet pas de faire du rendu, donc logiquement le TerrainRenderer devrait avoir une dépendance sur DynaTerrain)?
Pourquoi ne pas avoir simplement redécoupé le module DynaTerrain en "sous-modules"? Même si la classe RAII NzInitializer de Nazara permet d'initialiser plusieurs modules en une ligne, ça peut paraître plus lourd pour l'utilisateur.
Sinon que prévois-tu comme features une fois le(s) module(s) remis sur pied?
@Rinrynque : C'est pas tellement ce que je vais en faire, mais plutôt ce que les utilisateurs de Nazara feront comme jeu/applis avec Si déjà j'atteins les objectifs fixés, je serais très content !
@Raakz : Bonne question, en fait DynaTerrain aura une dépendance vers le TerrainRenderer. La classe DynamicTerrain (partie de DynaTerrain), à utiliser par les utilisateurs pour ajouter un terrain, fera elle même les appels au terrainRenderer. Elle initialisera le terrainRenderer si besoin.
Au final, c'est transparent pour l'utilisateur, car ajouter un terrain à la scène et le dessiner se fait comme tous les autres nodes. Le terrainRenderer lui-est invisible.
Enfin l'avantage de l'avoir découpé en deux modules bien distincts, c'est la réutilisation du code. Le terrainRenderer est capable de dessiner des terrainChunks, mais cette structure de donnée est très générique, au final c'est un vertexBuffer avec quelques fonctionnalités avancées. Il est possible que d'autres modules ou applications veuillent faire usage de ça, sans être dans l'optique d'un rendu de terrain. Alors c'est sûr, le choix du nom de terrainRenderer n'est peut être pas très judicieux, mais ça fait le taf pour l'instant.
Une fois ça de fait, il me reste toujours les points en rouge à implémenter, mais je pense qu'une fois le terrain fonctionnel, un système de modification temps-réel avec des brosses (pourquoi pas procédurales ^^) s'imposera !
Okay donc tu en as fait un module en vue d'une possible réutilisation des sparse et interval buffers, c'est vrai que si un autre module vient à s'en servir il faudra repenser le nom mais pour l'instant ça roule, je comprends mieux ton choix.
Donc l'utilisateur utilise DynaTerrain mais pas TerrainRenderer, (enfin si, mais pas directement).
Personnellement j'aimerais bien voir une démo de terrain infini ou une planète pour voir ce que ça donne!
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)
Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)
Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)
Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)