Русские документы
Ежедневные компьютерные новости RSS rusdoc.ru  Найти :
http://www.rusdoc.ru. Версия для печати.

Использование мегатекстур (megatexture, clipmaps).

Раздел: Разработка игр @ 09.11.2007 | Ключевые слова: megatexture clipmaps cliptexture мегатекстура

Автор: Евгений Головин
Источник: Евгений Головин

Автор: craft

В данной статье пойдет речь о том, как вывести изображение ландшафта, который покрыт одной большой, ну просто огромной текстурой (занимающей мегабайты, а то и гигабайты дискового пространства). И все это на обычных видеокартах.

 

Введение
Предыдущие подходы к текстурированию больших ландшафтов.
  Подсчет требуемой видеопамяти для растеризации.
Мегатекстура
  Подсчет требуемой видео памяти для растеризации.
  Таблица требуемой видео памяти для разных мегатекстур и размеров clipmap.
Clipmaps.
Оптимизация.
Некоторые схемы технологии clipmaps, говорящие сами за себя.
Персонажи в игре и др. объекты.
Выводы.
Различия технологий Megatexture и Clipmaps.
Вопросы?
Используемый материал.

Введение

Всё, что написано в данной статье, это лично мое мнение, основанное на доступных в Интернете материалах по данной тематике и личном опыте. Но я не претендую на последнюю инстанцию, а лишь надеюсь, что моя статья поможет вам разобраться в трюках мегатекстурирования и понять тот потенциал, который открывается с применением этой технологии.

Предыдущие подходы к текстурированию больших ландшафтов.

1. заливка областей одной текстурой – тайлинг и тайлсеты;
2. альфа-смешивание текстур;
3. вывод на экран относительно небольшой части ландшафта около игрока.

Плюсы:
1. небольшое количество текстур (небольшой объем данных);
2. относительная простота текстурирования.

Минусы:

1. ограниченное количество текстур (тайлов) приводит к сложностям в получении нужного рисунка, возможные комбинации всегда ограничены;
2. много повторяющегося рисунка на ландшафте;
3. ограничение в геометрии (например, только регулярная сетка) или наоборот, необходимость разбиения геометрии для формирования тайлсетов с разными тайлами.

Что будет, если задумать использовать одну текстуру на весь ландшафт?

Плюсы:

1. не будет тайлинга и тайлсетов;
2. не будет необходимости делать альфа смешивания разных текстур для формирования конечного рисунка в рантайме;
3. художник сможет просто рисовать любую часть ландшафта;
4. визуально реализм создаваемого ландшафта может быть увеличен в разы;
5. геометрия ландшафта может быть представлено как регулярной сеткой, так и любым мешем;
6. не будет необходимости бить геометрию для целей текстурирования.

Минусы:
1. объем текстуры для всего ландшафта будет занимать не мало места;
2. для ее подготовки понадобятся специальные инструменты и мощные компьютеры.

Честно говоря, я не уверен, что это явно минусы, так как текстуру можно пожать, а иметь быстрые компьютеры всегда здорово :)

Попробуем вывести ландшафт с уникальным рисунком.

Для этого загрузим в GPU текстуру высокого разрешения всего ландшафта, разумеется, со всеми ее уровнями детализации (mipmaps или лодами) и выведем всю геометрию ландшафта. GPU сам выберет нужный лод для растеризации конкретного пикселя на экране (или несколько лодов, в зависимости от установок). Например, для ближнего к камере пикселя будет выбран пиксель из детализированного лода, для дальнего – наоборот.

Все это понятно, но возьмем пример и подсчитаем необходимые объемы видеопамяти.

Подсчет требуемой видеопамяти для растеризации.

Пусть текстура нашего ландшафта будет иметь размер 4096 на 4096 пикселей. Первое ограничение, на которое мы наталкиваемся, это максимально поддерживаемое разрешение текстуры, которое может обрабатывать GPU. Далеко не все GPU могут работать с разрешением 4096 на 4096 пикселей (дело даже не 4096, т.к. всегда можно подобрать такое разрешение, которое не будет поддерживаться даже самой современной видео картой). Эта проблема может быть решена путем разрезания исходной текстуры на части. Тут довольно все просто, хотя не все! Разрезание может привести к необходимости разделения геометрии в местах стыка разных текстур, чтобы избежать попытки наложения на разные части одного треугольника двух и более текстур (несомненно, это усложнит геометрию, либо внесет дополнительные правила текстурирования). Вторая проблема – это объем памяти занимаемый текстурой. Для несжатой текстуры в нашем случае это:

4096 * 4096 * 4 = 64 Мб (при 32 битах на пиксель)

С лодами текстура займет более 85 Мб. А что делать, если размер исходной текстуры не 4096, а 8192 на 8192 пикселей? Это уже 341 Мб со всеми лодами. А если больше? Например, 1 квадратный км с разрешением 1 пиксель на 10 см будет покрывать мегатекстура с разрешением 10000 на 10000 пикселей. А ведь 1 пиксель на 10 см – это далеко не самое желаемое качество!

Совершено понятно, что при таких объемах GPU умрет. Использование сжатия текстуры не решит проблему кардинально, а лишь изменит максимально возможное разрешение.

Итого: очевидно, что такой способ не имеет общего решения, и его можно применить только в частных случаях для небольших ландшафтов и не больших текстур.

Так что же, забыть об одной детализированной текстуре на весь ландшафт?

Давайте поразмыслим. Мы знаем, что GPU для растеризации дальнего пикселя возьмет лод текстуры более простой, чем для растеризации ближнего пикселя, но в памяти GPU будут находиться все лоды!

А зачем тогда грузить лод высокой детализации в GPU при растеризации дальнего пикселя? Как сделать так, чтобы лишние лоды не грузились? Об этом в следующей части статьи.

Мегатекстура

Для более полного представления сути вопроса, предлагаю загрузить мой пример с использованием мегатекстуры:
http://www.rusdoc.ru/go.php?http://softvariant.ru/download/catalog/xForm2-mega-out.exe


Сама мегатекстура (textures/mega-8192.tga) имеет разрешение 8192 на 8192 и занимает 200Мб (24 бит на пиксель), поэтому самораспаковывающийся архив (по ссылке) довольно большой (он занимает 103 Мб).

Программа для запуска (test.exe) находится в папке bin. В первый запуск программа откомпилирует мегатекстуру, это может занять несколько минут, не прерывайте программу, она будет создавать файлы в папке textures/mega-8192 (и займет еще 260 Мб на «винте»). После того, как исходник текстуры откомпилируется, его (textures/mega-8192.tga) можно будет удалить (если он Вам не нужен).

Клавиши управления выводятся в самой программе на экране (стрелки курсора, LSHIFT – вверх, LCRTL – вниз, M (анг) – показать/убрать лоды).

Итак, в предыдущей части мы выяснили, что при  растеризации дальних пикселей в GPU желательно не загружать детализированные лоды (они не используются для растеризации), а для растеризации ближних пикселей все с точностью наоборот. Интуитивно понимаешь, что это может сэкономить много памяти, но сколько? Давайте придем к этому постепенно.

Предположим, игрок находится в центре ландшафта, тогда уровни детализации текстуры ландшафта, требуемые и используемые GPU для растеризации, будут выглядеть примерно так:


Схема 1.

Зеленый квадрат имеет самую лучшую детализацию, далее синий, желтый и малиновый. Каждый последующий занимает площадь на ландшафте в четыре раза больше и имеет в четыре раза худшую детализацию, чем предыдущий квадрат. А теперь внимание, Вам понятно, что разрешение части текстуры, охватываемой квадратами (с учетом ее детализации) одинаковое? Т.е. текстура, которая будет создана под зеленый квадрат, будет иметь такое же разрешение, как и под самый большой – малиновый.


Схема 2 (вид сбоку).

Когда я сказал про текстуру для зеленого квадрата, Вы не ослышались. Нам не нужна вся детализированная мегатекстура для того, чтобы построить вид из глаз игрока, находящегося в центре ландшафта. Нужна лишь небольшая часть вокруг него. Тоже касается и для остальных уровней детализации, пока мы не дойдем до последнего лода, который содержит уменьшенную копию всей мегатекстуры.

Необходимые части мегатекстуры для конкретных уровней детализации можно себе представить исходя из следующей схемы:


Схема 3.

Горизонтальные пунктирные линии показывают, какую площадь мегатекстуры должны содержать соответствующие уровни детализации.

В данной схеме (примере) камера находится достаточно высоко над ландшафтом, это привело к тому, что самый детализированный уровень (зеленый круг на схеме) не касается  ландшафта, значит, его мы может вообще не грузить в GPU! Это один из возможных путей оптимизации.

После того как в рантайме будут сформированы нужные части мегатекстуры, остается только вывести для каждого используемого уровня детализации геометрию ландшафта, которую он охватывает. Возможно, пока не очень понятно, но я предлагаю сейчас не останавливаться на этом, так как в самой технологии clipmaps техника растеризации будет более простой.

Подсчет требуемой видео памяти для растеризации.

Теперь давайте подсчитаем, сколько понадобиться видеопамяти для растеризации ландшафта покрытого мегатекстурой 8192 на 8192 пикселей.

Пусть игрок стоит на самом ландшафте, а не летает где-то в облаках (т.е. будем вести подсчет для всех уровней детализации). Возьмем размер clipmap 512 на 512 пикселей (512 clipmap). Clipmap – это область, которая вырезается из мегатекстуры вокруг игрока для каждого уровня детализации (лода). Чем она меньше, тем меньше детализированных пикселей будет видеть игрок перед собой, тем быстрее уровни детализации будут сменяться менее детализированными. Итак, поехали:

Вот и все!
Получилось 5 лодов по 512х512 пикселей каждый. Итого: 512 * 512 * 5 * 4 = 5 Мб (при 32 битах на пиксель). Формула следующая:
ClipmapWidth * ClipmapHeight * LodsNumber * BytesPerPixel.

Таблица требуемой видео памяти для разных мегатекстур и размеров clipmap.

 

На мой взгляд, наиболее оптимальные размеры clipmap (на текущий момент времени) находятся в приделах от 1024 до 2048.

Кстати, совершено не обязательно делать размер clipmap и разрешение мегатекстуры кратным степени 2!

Clipmaps.

Все, что я рассказывал до этого, было способом, который я использую в демонстрационном примере, он отличается от технологии clipmaps тем, что может быть реализован без применения пиксельных шейдеров (PS). Но применение PS позволяет существенно ускорить растеризацию, качество результирующей картинки и еще более упростить процесс.

Изменение в описанном алгоритме начинаются отсюда: «После того, как в рантайме будут сформированы нужные части мегатекстуры, остается только вывести для каждого используемого уровня детализации геометрию ландшафта, которую он охватывает». Так вот, в технологии clipmaps нужно просто вывести всю геометрию ландшафта за один проход, подав на вход PS подготовленные лоды, например, в текстурных регистрах или создать texture array для DirectX 10.

Еще одно важное замечание: для clipmaps все лоды должны иметь одинаковый размер, это существенно упростит PS (возможно это выглядело не явно, но в моем тестовом примере лоды могли иметь не одинаковые разрешения, см. схему 3).

Для того, чтобы в PS определить из какого лода брать пиксель, можно воспользоваться следующим алгоритмом:

float2 dx = ddx(input.texCoord * textureSize.x);



float2 dy = ddy(input.texCoord * textureSize.y);



float dd = max(sqrt(dx.x * dx.x + dx.y * dx.y)), sqrt(dy.x * dy.x + dy.y * dy.y)));



float mipLevel = log2(dd); 

Затем определить текстурные координаты:

float2 texCoord = input.texCoord / pow( 2, int(mipLevel) ) + 0.5;

В Nvidia SDK под DirectX 10 есть, кстати, пример работы с clipmaps!
http://www.rusdoc.ru/go.php?http://developer.download.nvidia.com/SDK/10/Samples/Clipmaps.zip

Оптимизация.


    1.  Как вы уже поняли, технология заключается в формировании в рантайме вокруг игрока лодов размером с clipmap, содержащих необходимую часть мегатекстуры. Пересоздавать лоды при каждом изменении игроком своей позиции было бы слишком накладно, поэтому делать это есть смысл, когда игрок отошел на некоторое расстояние от предыдущей позиции, участвовавшей в формировании текущих лодов.

    2.  Так как мегатекстура может занимать огромные объемы информации, есть смысл оптимизировать механизм адресации к нужным участкам мегатекстуры на диске. Для этого можно поделить все лоды мегатекстуры на блоки фиксированной величины, например, в моем тестовом примере это 128 на 128 пикселей. Также это увеличит кэшируемую часть мегатекстуры в памяти, что уменьшит количество обращений к диску.

    3.  У меня в тестовом примере мегатекстура разбита на фрагменты, которые находятся в папке textures\mega-8192. Это далеко не самый оптимальный вариант. Лучше поместить все фрагменты в один файл. Это позволит открыть файл с мегатекстурой только один раз при первом ее использовании в программе, что увеличит общую скорость подгрузки фрагментов с диска.

    4.  Фрагменты могут быть ужаты. Это не только увеличит скорость подгрузки, но и уменьшит объем мегатекстуры.

    5.  Фрагменты менее детализированных лодов будут видны игроку на некотором расстоянии от него, поэтому они могут быть ужаты с более высокими степенями сжатия за счет уменьшения качества (незначительные дефекты могут быть незаметны на расстоянии).

    6.  В программе должен быть реализован эффективный механизм кэширования фрагментов, чтобы, как минимум, не загружать с диска фрагменты, уже имеющиеся в памяти, а в идеале иметь в системной памяти как можно больше фрагментов, которые могут понадобиться в ближайшее время.

    7.  При формировании нужных частей мегатекстуры (вокруг игрока) нужно иметь в виду, что, скорее всего, далеко не все лоды будут нужны для растеризации (см. схему 3), это может существенно уменьшить объемы подгружаемых данных с диска и общий размер текстур, загружаемых в GPU.

    8.  Размер clipmap может быть не кратным 2, т.к. GPU уже давно умеют работать с такими текстурами.

    9.  Размер clipmap можно изменять на лету, например, при высокой скорости перемещения игрока размер clipmap можно уменьшить, это уменьшит количество подгружаемых фрагментов каждого уровня детализации, что приведет к общему уменьшению подгружаемых фрагментов. Кроме этого, уменьшится размер видео памяти, требуемой для растеризации.

Некоторые схемы технологии clipmaps, говорящие сами за себя.

 


Персонажи в игре и др. объекты.

Используемый подход с мегатекстурой наталкивает на то, чтобы при выводе персонажей, автомобилей и др. небольших объектов, также самому рассчитывать необходимый уровень детализации (один, два или три для возможности использование аппаратных средств фильтрации) и только их грузить в GPU, а не все лоды текстуры объекта. Это позволит иметь высокодетализированную текстуру объекта без ущерба  производительности и качества растеризации модели. Конечно, тут речь не идет о вырезании частей из текстуры объекта и применении полноценного clipmaps, достаточно просто выбрать нужные лоды всей текстуры, например, по расстоянию объекта от камеры.

Выводы.

 


    1.  Технология применения мегатекстур (clipmaps) позволяет практически снять ограничения на размер текстур, используемых в приложении (как по их разрешению, так и по их объему) и совершено не упирается в границы разрешений, поддерживаемых аппаратно GPU.

    2.  Художник может изменять любую область текстуры согласно концепт-дизайна без каких-либо на то ограничений со стороны технологии.

    3.  Технология позволяет в разы увеличить реалистичность виртуального мира.

    4.  Технология имеет высокий потенциал для оптимизации различных этапов.

    5.  Технологию полностью поддерживают аппаратная растеризация и возможности GPU.

Различия технологий Megatexture и Clipmaps.

Технология Clipmaps или ClipTextures была разработана компанией SGI и уже достаточно давно применяется для текстурирования больших ландшафтов. Суть технологии я описал в предыдущих частях.

Джон Кармак (John Carmack – co-owner, technical director, id Software) при разработке движка Tech 4 (финальная его версия была использована в игре Enemy Territory: Quake Wars) ввел термин megatexture. Его технология полностью повторяет clipmaps с добавлением следующих моментов: megatexture содержит еще bump карту, возможно спекуляр, информацию о типе материала (трава, камень и т.п.).

На мой взгляд, отличия мизерны. Но его название лучше отражает суть технологии и ее главные преимущества, в то время как название clipmaps лучше отражает программную реализацию.

Вопросы?

Добро пожаловать на форум статьи: http://www.rusdoc.ru/go.php?http://www.gamedev.ru/code/forum/?id=72131

Используемый материал.

1. OpenGL Performer Programmer`s Guide: ClipTextures
2. http://www.rusdoc.ru/go.php?http://www.modwiki.net/wiki/Id_Tech_4



Вернуться в раздел: Разработка игр
© Copyright 1998-2012 Александр Томов. All rights reserved.