Présentation
La principale raison de Virtual Texturing (VT), ou Sparse Virtual Textures , comme on l'appelle parfois, est comme une optimisation de la mémoire. L'essentiel de la chose est de ne déplacer dans la mémoire vidéo que les texels réels (généralisés en tant que pages / tuiles) dont vous pourriez avoir besoin pour une image rendue. Ainsi, il vous permettra d'avoir beaucoup plus de données de texture dans un stockage hors ligne ou lent (disque dur, disque optique, cloud) qu'il n'en aurait autrement sur la mémoire vidéo ou même la mémoire principale. Si vous comprenez le concept de mémoire virtuelle utilisé par les systèmes d'exploitation modernes, c'est la même chose dans son essence (le nom n'est pas donné par accident).
VT ne nécessite pas de recalculer les UV dans le sens où vous le feriez pour chaque image avant de rendre un maillage, puis soumettez à nouveau les données de sommet, mais cela nécessite un travail considérable dans les shaders Vertex et Fragment pour effectuer la recherche indirecte à partir des UV entrants. Dans une bonne implémentation cependant, elle devrait être complètement transparente pour l'application si elle utilise une texture virtuelle ou traditionnelle. En fait, la plupart du temps, une application mélangera les deux types de textures, virtuelle et traditionnelle.
Le traitement par lots peut en théorie très bien fonctionner, même si je n'ai jamais examiné les détails de cela. Étant donné que les critères habituels pour regrouper la géométrie sont les textures, et avec VT, chaque polygone de la scène peut partager la même texture "infiniment grande", théoriquement, vous pouvez obtenir un dessin de scène complet avec 1 appel de dessin. Mais en réalité, d'autres facteurs entrent en jeu, rendant cela impossible.
Problèmes avec VT
Le zoom avant / arrière et les mouvements brusques de la caméra sont les choses les plus difficiles à gérer dans une configuration VT. Cela peut sembler très attrayant pour une scène statique, mais une fois que les choses commencent à bouger, plus de pages / tuiles de texture seront demandées que vous ne pouvez en diffuser pour le stockage externe. Les entrées-sorties et les threads asynchrones peuvent aider, mais s'il s'agit d'un système en temps réel, comme dans un jeu, vous n'aurez qu'à effectuer le rendu pour quelques images avec des tuiles de résolution inférieure jusqu'à ce que celles en haute résolution arrivent, de temps en temps. , ce qui donne une texture floue. Il n'y a pas de solution miracle ici et c'est le plus gros problème avec la technique, l'OMI.
La texture virtuelle ne gère pas non plus la transparence de manière simple, les polygones transparents ont donc besoin d'un chemin de rendu traditionnel distinct pour eux.
Dans l'ensemble, VT est intéressant, mais je ne le recommanderais pas à tout le monde. Cela peut bien fonctionner, mais il est difficile à mettre en œuvre et à optimiser, et il y a juste trop de cas d'angle et de réglages spécifiques au cas nécessaires à mon goût. Mais pour les grands jeux en monde ouvert ou les applications de visualisation de données, cela pourrait être la seule approche possible pour adapter tout le contenu au matériel disponible. Avec beaucoup de travail, il peut être fait pour fonctionner assez efficacement même sur un matériel limité, comme nous pouvons le voir dans les versions PS3 et XBOX360 d'id's Rage .
la mise en oeuvre
J'ai réussi à faire fonctionner VT sur iOS avec OpenGL-ES, dans une certaine mesure. Mon implémentation n'est pas "livrable", mais je pourrais éventuellement le faire si je le voulais et si j'avais les ressources. Vous pouvez voir le code source ici , cela pourrait aider à avoir une meilleure idée de la façon dont les pièces s'assemblent. Voici une vidéo d'une démonstration exécutée sur iOS Sim. Il semble très lent car le simulateur est terrible pour émuler des shaders, mais il fonctionne bien sur un appareil.
Le diagramme suivant décrit les principaux composants du système dans mon implémentation. Il diffère un peu de la démo SVT de Sean (lien vers le bas), mais il est plus proche en architecture de celui présenté par le document Accelerating Virtual Texturing Using CUDA , trouvé dans le premier livre GPU Pro (lien ci-dessous).
Page Files
sont les textures virtuelles, déjà découpées en tuiles (pages AKA) en tant qu'étape de prétraitement, elles sont donc prêtes à être déplacées du disque vers la mémoire vidéo chaque fois que cela est nécessaire. Un fichier d'échange contient également l'ensemble des mipmaps, également appelés mipmaps virtuels .
Page Cache Manager
conserve une représentation côté application des textures Page Table
et Page Indirection
. Comme le déplacement d'une page du stockage hors ligne vers la mémoire coûte cher, nous avons besoin d'un cache pour éviter de recharger ce qui est déjà disponible. Ce cache est un cache LRU ( Least Latest Used ) très simple . Le cache est également le composant responsable de la mise à jour des textures physiques avec sa propre représentation locale des données.
Il Page Provider
s'agit d'une file d'attente de travaux asynchrones qui récupérera les pages nécessaires pour une vue donnée de la scène et les enverra dans le cache.
La Page Indirection
texture est une texture avec un pixel pour chaque page / tuile dans la texture virtuelle, qui mappera les UV entrants à la Page Table
texture de cache qui contient les données de texel réelles. Cette texture peut devenir assez grande, elle doit donc utiliser un format compact, comme RGBA 8: 8: 8: 8 ou RGB 5: 6: 5.
Mais il nous manque encore un élément clé ici, et c'est comment déterminer quelles pages doivent être chargées du stockage dans le cache et par conséquent dans le Page Table
. C'est là que le Feedback Pass et l' Page Resolver
entrée.
Le Feedback Pass est un pré-rendu de la vue, avec un shader personnalisé et à une résolution beaucoup plus basse, qui écrira les identifiants des pages requises dans le tampon de cadre couleur. Ce patchwork coloré du cube et de la sphère ci-dessus sont des index de page réels encodés en couleur RGBA. Ce rendu pré-passe est ensuite lu dans la mémoire principale et traité par le Page Resolver
pour décoder les index de page et déclencher les nouvelles requêtes avec le Page Provider
.
Après le pré-passage Feedback, la scène peut être rendue normalement avec les shaders de recherche VT. Mais notez que nous n'attendons pas la fin de la nouvelle demande de page, ce serait terrible, car nous bloquerions simplement les fichiers synchrones IO. Les demandes sont asynchrones et peuvent être prêtes ou non au moment du rendu de la vue finale. S'ils sont prêts, doux, mais sinon, nous gardons toujours une page verrouillée d'un mipmap basse résolution dans le cache comme solution de rechange, nous avons donc des données de texture à utiliser, mais cela va être flou.
Autres ressources à vérifier
La VT est toujours un sujet un peu brûlant sur l'infographie, donc il y a des tonnes de bons documents disponibles, vous devriez pouvoir en trouver beaucoup plus. S'il y a autre chose que je peux ajouter à cette réponse, n'hésitez pas à demander. Je suis un peu rouillé sur le sujet, je n'ai pas beaucoup lu à ce sujet au cours de la dernière année, mais c'est toujours bon pour la mémoire de revisiter des trucs :)
La texturation virtuelle est l'extrême logique des atlas de textures.
Un atlas de texture est une texture géante unique qui contient des textures pour des maillages individuels à l'intérieur:
Les atlas de texture sont devenus populaires en raison du fait que le changement de textures provoque une vidange complète du pipeline sur le GPU. Lors de la création des maillages, les UV sont compressés / décalés afin qu'ils représentent la «partie» correcte de l'ensemble de l'atlas de texture.
Comme @ nathan-reed l'a mentionné dans les commentaires, l'un des principaux inconvénients des atlas de texture est de perdre les modes d'habillage tels que la répétition, le pincement, la bordure, etc. En outre, si les textures n'ont pas assez de bordure autour, vous pouvez accidentellement échantillon d'une texture adjacente lors du filtrage. Cela peut entraîner des artefacts de saignement.
Les Atlas de texture ont une limitation majeure: la taille. Les API graphiques imposent une limite souple sur la taille d'une texture. Cela dit, la mémoire graphique n'est que si grande. Il y a donc aussi une limite stricte sur la taille de la texture, donnée par la taille de votre v-ram. Les textures virtuelles résolvent ce problème, en empruntant des concepts à la mémoire virtuelle .
Les textures virtuelles exploitent le fait que dans la plupart des scènes, vous ne voyez qu'une petite partie de toutes les textures. Donc, seul ce sous-ensemble de textures doit être en vram. Le reste peut être dans la RAM principale ou sur disque.
Il existe plusieurs façons de le mettre en œuvre, mais j'expliquerai la mise en œuvre décrite par Sean Barrett dans son discours sur GDC . (que je recommande fortement de regarder)
Nous avons trois éléments principaux: la texture virtuelle, la texture physique et la table de recherche.
La texture virtuelle représente le méga atlas théorique que nous aurions si nous avions assez de vram pour tout faire. Il n'existe en fait nulle part en mémoire. La texture physique représente les données de pixels que nous avons réellement en vram. La table de recherche est le mappage entre les deux. Pour plus de commodité, nous divisons les trois éléments en tuiles ou pages de taille égale.
La table de recherche stocke l'emplacement du coin supérieur gauche de la tuile dans la texture physique. Donc, étant donné un UV à la texture virtuelle entière, comment obtenir les UV correspondants pour la texture physique?
Tout d'abord, nous devons trouver l'emplacement de la page dans la texture physique. Ensuite, nous devons calculer l'emplacement des UV dans la page. Enfin, nous pouvons ajouter ces deux décalages ensemble pour obtenir l'emplacement des UV dans la texture physique
Calcul de pageLocInPhysicalTex
Si nous faisons de la table de recherche la même taille que le nombre de tuiles dans la texture virtuelle, nous pouvons simplement échantillonner la table de recherche avec l'échantillonnage du voisin le plus proche et nous obtiendrons l'emplacement du coin supérieur gauche de la page dans la texture physique.
Calculer inPageLocation
inPageLocation est une coordonnée UV relative à la partie supérieure gauche de la page plutôt qu'à la partie supérieure gauche de la texture entière.
Une façon de calculer cela est de soustraire les UV du coin supérieur gauche de la page, puis de les mettre à l'échelle de la taille de la page. Cependant, c'est un peu de maths. Au lieu de cela, nous pouvons exploiter la façon dont la virgule flottante IEEE est représentée. La virgule flottante IEEE stocke la partie fractionnaire d'un nombre par une série de fractions de base 2.
Dans cet exemple, le nombre est:
Voyons maintenant une version simplifiée de la texture virtuelle:
Le 1/2 bit nous indique si nous sommes dans la moitié gauche de la texture ou dans la droite. Le quart de bit nous indique dans quel quart de la moitié nous sommes. Dans cet exemple, puisque la texture est divisée en 16, ou 4 de côté, ces deux premiers bits nous disent dans quelle page nous sommes. Le reste les bits nous indiquent l'emplacement à l'intérieur de la page.
Nous pouvons obtenir les bits restants en déplaçant le flotteur avec exp2 () et en les supprimant avec fract ()
Où numTiles est un int2 donnant le nombre de tuiles par côté de la texture. Dans notre exemple, ce serait (4, 4)
Calculons donc l'inPageLocation pour le point vert, (x, y) = (0.6875, 0.375)
Une dernière chose à faire avant que nous ayons terminé. Actuellement, inPageLocation est une coordonnée UV dans «l'espace» de texture virtuelle. Cependant, nous voulons une coordonnée UV dans «l'espace» de texture physique. Pour ce faire, nous devons simplement mettre à l'échelle inPageLocation par le rapport entre la taille de la texture virtuelle et la taille de la texture physique
La fonction terminée est donc:
la source