Si la scène ne tient pas entièrement en mémoire, vous entrez dans le domaine du rendu hors noyau. Il existe essentiellement deux approches ici: a) Générez votre scène à la demande b) Chargez votre scène à la demande
L'ancienne approche s'accorde bien avec la plupart des workflows d'animation, où les modèles sont fortement subdivisés en utilisant par exemple Catmull-Clark et peuvent devenir très gourmands en mémoire, mais les maillages de base eux-mêmes s'insèrent facilement dans la mémoire. Pixar a quelques articles à ce sujet (par exemple, les différentiels de rayons et la mise en cache de géométrie multirésolution pour le traçage des rayons de distribution dans les scènes complexes ), mais l'essentiel est que les modèles ne sont subdivisés que lorsqu'ils sont frappés par un rayon, et seulement subdivisés autant qu'ils le sont. raisonnable pour un tel rayon (par exemple, l'interréflexion diffuse nécessite moins de précision que les réflexions miroir). Le reste est géré par un cache de géométrie, qui conserve les modèles subdivisés en mémoire et, espérons-le, rend le processus efficace par une bonne stratégie d'éviction.
Tant que tous vos maillages de base s'insèrent confortablement dans la mémoire, vous pouvez facilement sortir du cœur et rendre les maillages à des niveaux de subdivision qui ne rentreraient jamais dans la mémoire. Le cache de géométrie évolue également bien avec la quantité de mémoire dont vous disposez, vous permettant de peser la RAM par rapport aux temps de rendu. Cela a également été utilisé dans les voitures, je crois.
La deuxième approche est plus générale et ne repose pas sur un usage intensif de la subdivision. Au lieu de cela, il repose sur le fait que votre scène a probablement été réalisée par un artiste et est déjà partitionnée en objets relativement petits qui s'inscrivent dans la mémoire individuellement. L'idée est alors de conserver deux hiérarchies (arborescence kD ou hiérarchie de volume englobant): une hiérarchie de niveau supérieur qui ne stocke que les boîtes englobantes des objets de votre scène et une hiérarchie de bas niveau qui stocke la géométrie réelle. Il existe une telle hiérarchie de bas niveau pour chaque objet.
Dans cette approche, vous stockez idéalement déjà une boîte englobante avec chaque objet sur le disque. Lorsque la scène est chargée, vous ne créez initialement que la hiérarchie de niveau supérieur, ce qui signifie que vous n'avez qu'à regarder les boîtes englobantes et non la géométrie. Vous commencez ensuite à tracer des rayons et à les parcourir dans la hiérarchie. Chaque fois qu'un rayon frappe un nœud feuille dans la hiérarchie de niveau supérieur (c'est-à-dire qu'il frappe la boîte englobante d'un objet), cet objet est chargé en mémoire et sa hiérarchie de bas niveau est créée. Le rayon continue ensuite à suivre cet objet. Combiné avec un cache d'objets qui conserve autant de la hiérarchie de bas niveau en mémoire que possible, cela peut fonctionner raisonnablement bien.
Le premier avantage d'une telle approche est que les objets qui ne sont jamais touchés ne sont jamais chargés, ce qui signifie qu'elle s'adapte automatiquement à la visibilité de votre scène. Le deuxième avantage est que si vous tracez de nombreux rayons, vous n'avez pas besoin de charger un objet immédiatement car il est frappé par un rayon; au lieu de cela, vous pouvez maintenir ce rayon et attendre jusqu'à ce que suffisamment de rayons aient frappé cet objet, amortissant la charge sur plusieurs coups de rayon.
Vous pouvez également combiner cette approche avec un algorithme de tri des rayons tel que Ombrage différé trié pour le suivi du chemin de production pour éviter le thrashing dû aux rayons incohérents. L'article mentionné décrit l'architecture du moteur de rendu Hyperion de Disney, utilisé pour Big Hero 6, je crois, de sorte qu'il peut très probablement gérer des scènes à l'échelle de la production.
Si vous organisez votre scène dans une structure spatiale (la manière habituelle étant une hiérarchie de volume englobante ), vous pouvez utiliser une sorte de scène virtuelle (je compose ce terme, en référence aux textures virtuelles ).
Un gestionnaire de mémoire ne garderait qu'un nombre limité de boîtes englobantes chargées à la fois et résumerait l'opération consistant à en récupérer une.
De cette façon, une boîte serait chargée uniquement selon les besoins: lorsqu'un rayon frappe une boîte englobante, la boîte est chargée pour résoudre la collision. Plus tard, lorsqu'une autre boîte doit être chargée, celle qui n'est pas utilisée est supprimée pour faire place à la nouvelle.
Avec toutes ces boîtes chargées et supprimées, la cohérence des rayons serait un facteur majeur de vitesse. Je suppose qu'une autre amélioration pourrait être de différer le chargement, en réorganisant les rayons pour traiter d'abord les boîtes qui sont déjà chargées.
la source
Ce que vous faites est de charger des triangles en mémoire à partir du disque en fonction de ce qui a été frappé précédemment. Vous pouvez commencer par des triangles à proximité immédiate en premier. Le raisonnement est que dans une zone, les rayons sont susceptibles de frapper les mêmes triangles à plusieurs reprises. Et finalement, vous serez quelque peu efficace. (Pour cette raison, c'est une bonne idée de mettre en cache le dernier triangle frappé dans le traçage d'occlusion qui ne se soucie pas de l'ordre)
Deuxièmement, vous stockez les triangles dans une arborescence spatiale qui vous permet d'effectuer une recherche rapide à partir du disque, pour renouveler les portions que vous avez en mémoire par proximité. Ne chargez donc que les branches qui gêneront le rayon. Si c'est une sorte d'arbre voxel, comme un octree, vous pouvez même trier les rayons secondaires et les résoudre par cohérence. Un arbre BSP est également assez bon dans les zones d'élagage.
Il y a des cas où cela échoue mais c'est raisonnablement efficace dans la plupart des compartiments de scène si vous ne rendez pas de bruit ...
la source