Graphique de scène pour le moteur de rendu différé

10

Comme exercice d'apprentissage, j'ai écrit un moteur de rendu différé. Maintenant, j'aimerais ajouter un graphique de scène à ce moteur, mais je suis un peu perplexe sur la façon de procéder.

Sur un moteur normal (moteur de rendu vers l'avant), j'ajouterais simplement tous les éléments (tous implémentant IDrawable et IUpdateAble) à mon graphique de scène, puis parcourez d'abord l'étendue du graphique de scène et appelez Draw () partout.

Cependant, dans un moteur de rendu différé, je dois séparer les appels de tirage. Je dois d'abord dessiner la géométrie, puis les lanceurs d'ombres et ensuite les lumières (toutes vers différentes cibles de rendu), avant de les combiner toutes. Dans ce cas, je ne peux pas simplement parcourir le graphique de la scène et appeler simplement draw. De la façon dont je le vois, je dois soit parcourir le graphique de la scène entière 3 fois, vérifier le type d'objet à dessiner, soit créer 3 graphiques de scène distincts qui sont en quelque sorte connectés les uns aux autres. Ces deux solutions semblent médiocres, je voudrais gérer des objets de scène plus transparents.

Une autre solution à laquelle j'ai pensé était de parcourir le graphique de la scène comme d'habitude et d'ajouter des éléments à 3 listes distinctes, de séparer la géométrie, les roulettes d'ombre et les lumières, puis d'itérer ces listes pour dessiner les bonnes choses, est-ce mieux et est-ce sage de repeupler 3 listes à chaque trame?

Roy T.
la source

Réponses:

6

Une approche que j'ai utilisée dans un projet C ++ est que le graphe de scène (qui a l'index spatial) remplit un vecteur std :: «visible» de hits basé sur le tronc de visualisation actuel. Cette liste visible est gérée par le graphique de la scène et n'est donc recalculée que lorsque la caméra se déplace - les objets en mouvement dans le graphique sont déplacés dans cette liste et utilisent des pierres tombales et des listes de modifications non triées qui sont triées et fusionnées en fonction des besoins.

La liste des éléments visibles est d'abord triée par ID de shader et dans chaque type par distance de la caméra. Les ID de shader sont attribués de telle sorte que le terrain trie d'abord, puis les bâtiments, puis les unités, puis les projectiles, puis les particules, etc. - il s'agit d'un RTS. Certains modèles ont plus d'un shader, mais ils annoncent uniquement leur shader principal. Lorsqu'on leur demande de dessiner, ceux qui ont besoin de bits dessinés avec un autre shader s'ajoutent également à une liste chaînée unique de passage suivant.

Ainsi, le dessin parcourt le tableau visible en une seule passe, et en cette passe, une liste liée de ces éléments à revisiter est créée, et ils sont dessinés une deuxième passe et ainsi de suite.

Le dessin d'avant en arrière et opaque puis transparent aide à garder tout sain d'esprit.

Cela ne minimise peut-être pas le nombre de changements de shaders, etc., mais il est assez pratique et simple à mettre en œuvre.

Je n'ai aucune idée de XNA, de son applicabilité et de la quantité de ce contenu de bas niveau que vous créez, je le crains. Il serait cependant très intéressant de savoir ce que les vétérans pensent de cette approche pour les CTS RTS.

Volonté
la source
Hey Will, j'aime vraiment cette réponse, surtout parce qu'elle est totalement différente de ce à quoi j'ai pensé jusqu'à présent. Votre méthode semble très sensée, surtout quand vous pensez également aux objets semi-transparents (que je viens surtout d'éviter jusqu'à présent). Construire une liste (liée) à partir de votre graphique de scène pour les objets à visiter semble être une très bonne idée. Et oui dans XNA, nous devons aussi faire tout ce truc de bas niveau :).
Roy T.
3

Ma suggestion serait une approche en 2 étapes adaptée à vos besoins spécifiques, similaire à ce que vous avez décrit vous-même. Vous avez besoin d'un graphique de scène et d'une "collection de rendus" pour chacune des étapes de rendu, dans votre cas l'ombre, la géométrie, les lumières (peut-être un quatrième étant des objets transparents?)

Le graphique de la scène peut être basé sur n'importe quel type de relations, mais ma préférence personnelle serait basée sur des relations spatiales où chaque nœud peut contenir les autres nœuds pour faciliter une élimination rapide.

Les collections de rendu peuvent être n'importe quel type de structure de données adaptée à l'étape spécifique. Par exemple, la collection d'ombres peut être une liste ou un arbre trié par profondeur pour maximiser le rejet précoce z. La collection de géométries peut être triée par utilisation de shader pour minimiser les changements de shader (état). La collection de lumière peut être une liste ou un arbre trié par distance de lumière, taille ou une combinaison de ceux-ci afin que vous puissiez limiter le rendu de la lumière aux seules lumières les plus efficaces si les performances sont un problème.

Quelles que soient les structures de données que vous choisissez, assurez-vous que l'opération d'insertion est rapide et assurez-vous qu'elle utilise le regroupement et d'autres techniques pour éliminer toute allocation / destruction de données, car vous effacerez et remplirez ces listes à chaque trame.

Maintenant, il est facile de tout lier ensemble. Parcourez simplement le graphique de la scène et ajoutez chaque élément à la ou aux collections de rendu appropriées. Cela aide si votre structure de données trie / structure automatiquement les nouvelles entrées en fonction des exigences. Lorsque vous avez terminé, parcourez les collections de rendu dans l'ordre requis et rendez-les.

Parce que vos structures de données ont une insertion rapide et ne génèrent pas de déchets, il n'y a pas de pénalité pour le repeuplement des listes comme vous l'avez mentionné.

Marché
la source