Méthode efficace de rendu de terrain massif dans XNA

10

Je crée un jeu XNA qui nécessite un espace énorme pour les joueurs. Actuellement, la hauteur de test que j'utilise est 4096x4096 et est enregistrée en tant que BMP 4 bits.

Ce que j'essaie de faire, c'est de prendre cet énorme fichier de hauteur et de le rendre dans le jeu. Le problème que je rencontre est le fait qu'il est inefficace de charger tout le terrain en mémoire à la fois, car il utilisera la majorité de la mémoire disponible.

Un autre problème que j'ai rencontré est que je ne peux pas rendre le terrain tout en une primitive en raison d'un ensemble de limites strictes dans XNA.

Cela dit, j'ai rencontré un certain nombre de solutions, que j'ai énumérées ci-dessous:

  • Rendu basé sur l'emplacement actuel de l'utilisateur - dessiner essentiellement un carré autour de l'utilisateur, quelle que soit son orientation dans le monde. Ce n'est pas exactement ce que je voulais non plus, car vous restituez toujours de l'espace que l'utilisateur ne voit pas.
  • Rendu basé sur l'orientation et la position de l'utilisateur - J'ai trouvé une formule pour récupérer un triangle censé avoir les pixels de la carte de hauteur censés être rendus, mais cela s'est avéré très difficile.
  • Diviser le terrain en plusieurs morceaux et rendre ceux qui sont les plus proches de l'utilisateur - Toujours pas très efficace car vous restituez toujours des morceaux que les gens ne verront pas. Et cela demande beaucoup de travail, car je dois ensuite diviser ma carte de hauteur en plusieurs parties, et l'évolutivité devient un gros problème.

Après avoir essayé ces solutions, je suis à court d'idées pour savoir quoi faire. J'ai reçu des réponses où les gens me disent de faire ces algorithmes complexes, mais je n'ai tout simplement aucune idée même de la façon de les faire.

Donc, fondamentalement, je demande un moyen simple et direct de rendre des terrains énormes dans XNA avec une efficacité maximale.

Je suis plutôt nouveau dans le développement de jeux en général, mais je suis prêt à faire des recherches si cela semble prometteur.

Mise à jour 1: Après avoir recherché la méthode de géoclipmapping, j'ai commencé à coder avec ça. J'ai fait tous les calculs et le jeu se déroule. Cependant, il est extrêmement inefficace - ce qui est probablement un mauvais codage de ma part. Il fonctionne à 2FPS et utilise un cœur entier de mon processeur. Je vais essayer d'améliorer le code, mais je pense que j'aurai besoin de plus d'aide, alors voici un Pastebin du code pour la classe Terrain manager. Je posterai plus de résultats plus tard si je parviens à être plus efficace.

sammarks
la source
1
Fait intéressant, la technique dont vous parlez semble similaire à celle qu'ID Software utilise dans son prochain jeu, Rage. Ils utilisent une «megatexture», puis diffusent les parties nécessaires dans le GPU. Il a fait un discours à ce sujet, mais voici un article de wikipedia, il pourrait être source d'inspiration: en.wikipedia.org/wiki/MegaTexture

Réponses:

5

L'approche par morceaux est généralement ce qui est utilisé. Il est rarement efficace de tester chaque triangle sur des centaines de milliers pour voir si vous devez le rendre. Au lieu de cela, la plupart des algorithmes de rendu de terrain utilisent une structure de données spatiales pour restituer dynamiquement les parties visibles du terrain.

Une structure de données facile à implémenter est appelée quadtree . En bref, pour utiliser un quadtree, vous trouverez le tronc de visualisation du joueur, l'intersectez avec le niveau supérieur du quadtree et pour tous les morceaux qui sont partiellement visibles (c'est-à-dire que les plans du tronc coupent le morceau), vous subdivisez et testez tous les enfants morceaux, en omettant ceux en dehors du tronc. Cela donnera une approximation assez proche de la géométrie visible réelle avec seulement quelques niveaux de récursivité.

Des rendus de terrain plus avancés utilisent un algorithme pour régler non seulement la géométrie visible, mais aussi les détails de cette géométrie. Le géomipmapping (et son géoclipmapping relatif) est relativement populaire pour le moment, mais ce n'est pas une chose triviale à mettre en œuvre.

edit: Voici une description décente de la géoclipmapping et de l'abattage du tronc.

J'ai également un doute quant à savoir si 4 bits pour la carte de hauteur sont réellement suffisants pour produire un terrain agréable à moins que vous ne fassiez beaucoup de lissage sur le résultat.

Ron Warholic
la source
J'ai jeté un coup d'œil à cet article et j'ai décidé que j'allais d'abord utiliser la méthode de géoclipmapping, car il semble que ce serait le plus efficace pour afficher une grande quantité de terrain. Je reviendrai avec mes résultats.
3

Toute approche qui vous oblige à effectuer un travail par trame pour charger des données sur le GPU sera défectueuse.

Voici un aperçu d'une approche qui devrait bien fonctionner:

Vous devriez diviser votre terrain en morceaux (assez gros), en chargeant ces morceaux dans des tampons de vertex fixes (la profondeur de bits de votre carte de hauteur n'a pas d'importance!). Ces tampons de vertex resteront simplement dans la mémoire du GPU, en attendant d'être rendus. Vous devrez expérimenter ce qui est une taille de bloc appropriée, mais 128x128 est peut-être un bon point de départ.

Pour un terrain de 4096 x 4096, vous êtes un peu au-delà de la limite de ce que je serais à l'aise de charger sur le GPU à la fois - c'est probablement quelques centaines de Mo de données de sommet (bien que vous puissiez le ramener à ~ 64 Mo si vous êtes intelligent). Vous devrez donc peut-être charger et décharger des tampons de vertex du GPU en arrière-plan.

(Si vous implémentez le chargement en arrière-plan de morceaux, cela devrait être extrêmement évolutif!)

Une fois que vous avez les données de sommet sur le GPU, c'est le moment approprié pour effectuer une élimination de la visibilité par bloc . Il n'est pas nécessaire d'envoyer la commande pour rendre un morceau, si vous savez qu'il est derrière la caméra.

Vous ne devriez presque jamais effectuer d' élimination par triangle sur le processeur!

Le GPU supprimera les triangles hors écran beaucoup plus rapidement que vous ne pourrez jamais le faire.

Pour plus d'informations sur les performances, consultez cette réponse sur le site Game Dev.

Andrew Russell
la source
0

Je ne suis en aucun cas un expert de XNA, alors corrigez-moi si je me trompe, mais j'avais l'impression qu'il existe en fait une optimisation intégrée pour des situations comme celle-ci. Je sais que vous pouvez définir une distance de rendu et après ce point, il ne restitue rien, dans votre cas, ce serait le terrain restant. Cependant, cela laisse un avantage assez peu attrayant à votre monde rendu, vous devrez donc implémenter quelque chose comme la buée que la plupart des jeux du monde ouvert ont.

Karoly S
la source
Il existe des solutions intégrées, mais le problème que j'ai rencontré était que j'essayais de rendre une grande primitive, qui dépassait la limite de polygones pour les primitives. Par conséquent, il ne dessinerait pas, il suffit de lever une exception.
sammarks