обзор
Основная причина виртуального текстурирования (VT) или разреженных виртуальных текстур , как его иногда называют, заключается в оптимизации памяти. Суть в том, чтобы перемещать в видеопамять только те тексели (обобщенные как страницы / фрагменты), которые вам могут понадобиться для визуализированного кадра. Таким образом, это позволит вам иметь гораздо больше текстурных данных в автономном или медленном хранилище (HDD, Optical-Disk, Cloud), чем в противном случае поместится в видеопамять или даже основную память. Если вы понимаете концепцию виртуальной памяти, используемой современными операционными системами, это то же самое по своей сути (название не дано случайно).
VT не требует повторного вычисления UV в том смысле, что вы должны делать это каждый кадр перед рендерингом меша, а затем повторно передавать данные вершин, но для этого требуется некоторая существенная работа в шейдерах Vertex и Fragment для выполнения косвенного поиска от входящих UV. Однако в хорошей реализации оно должно быть полностью прозрачным для приложения, если оно использует виртуальную текстуру или традиционную. На самом деле, в большинстве случаев приложение будет смешивать оба типа текстурирования, виртуальное и традиционное.
Пакетная обработка в теории может работать очень хорошо, хотя я никогда не изучал детали этого. Поскольку обычными критериями для группировки геометрии являются текстуры, а с VT каждый полигон в сцене может иметь одну и ту же «бесконечно большую» текстуру, теоретически вы можете добиться полного рисования сцены с помощью одного вызова отрисовки. Но на самом деле в игру вступают другие факторы, делающие это непрактичным.
Проблемы с VT
Увеличение / уменьшение и резкое движение камеры - самые сложные вещи в настройке VT. Это может выглядеть очень привлекательно для статичной сцены, но как только вещи начнут двигаться, будет запрошено больше страниц / плиток текстуры, чем вы можете передать для внешнего хранения. Асинхронный ввод-вывод файлов и многопоточность могут помочь, но если это система реального времени, как в игре, вам просто нужно будет рендерить несколько кадров с плитками с более низким разрешением, пока не появятся изображения с высоким разрешением, время от времени , в результате чего получается размытая текстура. Здесь нет серебряной пули, и это самая большая проблема с техникой, ИМО.
Виртуальное текстурирование также не позволяет легко управлять прозрачностью, поэтому для прозрачных полигонов необходим отдельный традиционный путь рендеринга.
В общем, VT интересен, но я бы не рекомендовал его всем. Он может хорошо работать, но его трудно реализовать и оптимизировать, плюс на мой вкус нужно слишком много угловых случаев и настроек для конкретного случая. Но для больших игр с открытым миром или приложений для визуализации данных, это может быть единственно возможным подходом - поместить весь контент в доступное оборудование. С большой работой можно заставить работать довольно эффективно даже на ограниченном оборудовании, как мы видим в версиях id Rage для PS3 и XBOX360 .
Реализация
Мне удалось в некоторой степени заставить VT работать на iOS с OpenGL-ES. Моя реализация не является "отправляемой", но я мог бы сделать это, если бы захотел и имел ресурсы. Вы можете просмотреть исходный код здесь , это может помочь получить лучшее представление о том, как части сочетаются друг с другом. Вот видео демонстрации, работающей на iOS Sim. Это выглядит очень запаздывающим, потому что симулятор ужасен при эмуляции шейдеров, но работает на устройстве плавно.
На следующей диаграмме представлены основные компоненты системы в моей реализации. Он немного отличается от демонстрации SVT Шона (ссылка внизу), но по архитектуре он ближе к тому, что представлен в статье « Ускорение виртуального текстурирования с использованием CUDA» , описанной в первой книге GPU Pro (ссылка ниже).
Page Files
Это виртуальные текстуры, уже разрезанные на листы (страницы AKA) в качестве шага предварительной обработки, поэтому они готовы для перемещения с диска в видеопамять при необходимости. Файл страницы также содержит полный набор мип-карт, также называемых виртуальными мип-картами .
Page Cache Manager
сохраняет приложения бокового представления Page Table
и Page Indirection
текстур. Поскольку перемещение страницы из автономного хранилища в память обходится дорого, нам необходим кэш, чтобы избежать перезагрузки того, что уже доступно. Этот кеш является очень простым кешем с наименьшим количеством использованных ресурсов (LRU). Кэш также является компонентом, отвечающим за поддержание физических текстур в актуальном состоянии с помощью собственного локального представления данных.
Это Page Provider
асинхронная очередь заданий, которая извлекает страницы, необходимые для данного вида сцены, и отправляет их в кэш.
Page Indirection
Текстура текстуры с одного пикселя для каждой страницы / плитки в виртуальной текстуры, которая будет картировать входящие UVs к Page Table
текстуре кэша , который имеет фактические данные текселя. Эта текстура может быть довольно большой, поэтому она должна использовать какой-то компактный формат, например RGBA 8: 8: 8: 8 или RGB 5: 6: 5.
Но нам все еще не хватает ключевой части здесь, и именно так определяется, какие страницы должны быть загружены из хранилища в кеш и, следовательно, в Page Table
. Вот где проходит обратная связь и Page Resolver
вход.
Пропуск обратной связи - это предварительный рендеринг вида с пользовательским шейдером и гораздо более низким разрешением, который записывает идентификаторы требуемых страниц в цветной кадровый буфер. Эта цветная мозаика куба и сферы выше - это реальные индексы страниц, закодированные в цвете RGBA. Этот предварительный рендеринг затем считывается в основную память и обрабатывается Page Resolver
для декодирования индексов страниц и запуска новых запросов с помощью Page Provider
.
После предварительного прохождения Feedback, сцена может быть визуализирована в обычном порядке с помощью шейдеров поиска VT. Но обратите внимание, что мы не ждем завершения запроса новой страницы, это было бы ужасно, потому что мы просто заблокировали бы синхронный ввод-вывод файла. Запросы являются асинхронными и могут быть, а могут и не быть готовы к моменту представления окончательного представления. Если они готовы, мило, но если нет, мы всегда сохраняем заблокированную страницу мип-карты с низким разрешением в кэше как запасной вариант, поэтому у нас есть некоторые данные текстуры, которые можно использовать, но они будут размытыми.
Другие ресурсы стоит проверить
VT по-прежнему остается горячей темой по компьютерной графике, поэтому доступно множество хороших материалов, и вы сможете найти гораздо больше. Если есть что-то еще, что я могу добавить к этому ответу, пожалуйста, не стесняйтесь спрашивать. Я немного заржавел по этой теме, мало что читал об этом за последний год, но для памяти всегда полезно пересматривать вещи :)
Виртуальное текстурирование - логическая крайность текстурных атласов.
Текстурный атлас - это гигантская текстура, в которой содержатся текстуры для отдельных сеток:
Текстурные атласы стали популярными благодаря тому, что изменение текстур приводит к полной очистке конвейера на GPU. При создании ячеек UV сжимаются / сдвигаются так, чтобы они представляли правильную «часть» всего текстурного атласа.
Как отметил @ nathan-reed в комментариях, одним из основных недостатков текстурных атласов является потеря режимов обтекания, таких как повторение, зажим, граница и т. Д. Кроме того, если текстуры не имеют достаточного количества границ вокруг них, вы можете случайно выборка из смежной текстуры при выполнении фильтрации. Это может привести к артериальным кровотечениям.
Текстурные атласы имеют одно главное ограничение: размер. Графические API накладывают мягкое ограничение на то, насколько большой может быть текстура. Тем не менее, графическая память только так велика. Таким образом, существует также жесткое ограничение на размер текстуры, определяемое размером вашего виртуального тома. Виртуальные текстуры решают эту проблему, заимствуя понятия из виртуальной памяти .
Виртуальные текстуры используют тот факт, что в большинстве сцен вы видите только небольшую часть всех текстур. Итак, только то подмножество текстур должно быть в vram. Остальное может быть в оперативной памяти или на диске.
Есть несколько способов реализовать это, но я объясню реализацию, описанную Шоном Барреттом в его выступлении на GDC . (который я очень рекомендую смотреть)
У нас есть три основных элемента: виртуальная текстура, физическая текстура и таблица соответствия.
Виртуальная текстура представляет теоретический мега атлас, который был бы у нас, если бы у нас было достаточно vram, чтобы вместить все. Это на самом деле не существует в памяти нигде. Физическая текстура представляет, какие данные о пикселях у нас есть в vram Таблица поиска - это отображение между ними. Для удобства мы разбиваем все три элемента на плитки одинакового размера или страницы.
Таблица поиска хранит расположение верхнего левого угла плитки в физической текстуре. Итак, учитывая UV для всей виртуальной текстуры, как мы можем получить соответствующее UV для физической текстуры?
Во-первых, нам нужно найти местоположение страницы в физической текстуре. Затем нам нужно рассчитать местоположение УФ на странице. Наконец, мы можем добавить эти два смещения вместе, чтобы получить местоположение УФ в физической текстуре
Расчет страницыLocInPhysicalTex
Если мы сделаем таблицу поиска того же размера, что и количество плиток в виртуальной текстуре, мы можем просто сэмплировать таблицу поиска с выборкой ближайшего соседа, и мы получим расположение верхнего левого угла страницы в пределах физической текстуры.
Расчет inPageLocation
inPageLocation - это UV-координата, относящаяся к верхнему левому углу страницы, а не к верхнему левому краю всей текстуры.
Один из способов рассчитать это - вычесть ультрафиолетовое излучение в верхней левой части страницы, а затем масштабировать до размера страницы. Тем не менее, это довольно немного математики. Вместо этого мы можем использовать представление IEEE с плавающей запятой. IEEE с плавающей запятой хранит дробную часть числа в виде серии из 2 основных дробей.
В этом примере число:
Теперь давайте посмотрим на упрощенную версию виртуальной текстуры:
1/2 бит говорит нам, находимся ли мы в левой половине текстуры или справа. 1/4 бита говорит нам, в какой четверти половины мы находимся. В этом примере, поскольку текстура разбита на 16 или 4 в сторону, эти первые два бита говорят нам, на какой странице мы находимся. биты говорят нам расположение внутри страницы.
Мы можем получить оставшиеся биты, сдвинув float с помощью exp2 () и удалив их с помощью fract ()
Где numTiles - это int2, указывающая количество плиток на каждой стороне текстуры. В нашем примере это будет (4, 4)
Итак, давайте рассчитаем inPageLocation для зеленой точки, (x, y) = (0,6875, 0,375)
Последнее, что нужно сделать, прежде чем мы закончим. В настоящее время inPageLocation представляет собой UV-координату в виртуальной текстуре «space». Тем не менее, мы хотим, чтобы координата UV в физической текстуре «пространство». Для этого нам просто нужно масштабировать inPageLocation по отношению размера виртуальной текстуры к физическому размеру текстуры.
Итак, готовая функция:
источник