суббота, 30 апреля 2011 г.

Параллельно разбитые Карты теней (shadow maps) на Программируемых GPU–Часть 3

 

Оригинал статьи:

http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html

Генерация теней

Конвейер рендеринга выглядит подобно тому, как в DirectX 9. Главное различие - то, что мы визуализируем теневые карты только однажды. Кроме того, мы теперь должны сохранять матрицы сжатия каждого разбиения в массив, потому что она нам понадобится шейдерах.

Что более важно, после обнаружения потенциальных объектов отбрасывающих тень для разбиения, для каждого объекта нам нужно следить за двумя переменными: firstSplit и lastSplit. Эти переменные определяют диапазон индексов разбиения, в которые отбрасывающий тень объект должен быть спроецирован, как показано на иллюстрации 10-10. Отметим, что мы должны сохранить только первые и последние индексы, потому что непрерывная форма ограничения будет всегда накладываться на непрерывный диапазон частей разбиения.

clip_image002

Иллюстрация 10-10.

Поскольку мы начинаем визуализировать теневые карты, мы должны установить новую область просмотра и изменить цели рендеринга, как показано в листинге 10-8, где переменная pDSV указывает на ранее созданное представление трафарета глубины. Поскольку мы визуализируем только информацию глубины, мы должны установить номер установить номер объекта рендеринга в 0, а выполняющийся целевой указатель в NULL.

Пример 10-8. Активизация рендеринга теневой карты

clip_image004

Тогда мы выводим каждый объект, отбрасывающий тень лишь однажды, но в специальном цикле рендеринга. В этом цикле мы должны обновлять константы шейдеров firstSplit и lastSplit с соответствующими значениями от объекта, отбрасывающего тень. Поскольку эти переменные - "perinstance"-данные, они должны обрабатывать, например, матрицу всех объектов.

Далее мы представляем два различных подхода для того, чтобы динамически клонировать геометрию для различных разбиений.

Использование клонирования шейдеров.

В этом первом методе мы используем геометрический шейдер, чтобы дублировать, представленные треугольники в различные объекты рендеринга. Эта методика подобна однопроходной методике карты куба, представленной в DirectX Microsoft SDK. Сначала объясним подробности здесь, и затем обсудим преимущества производительности.

С этой методикой вершинный шейдер просто преобразовывает каждую вершину с матрицей мира, матрицей представления освещения, и матрицей проекции освещения. Это преобразование характерно для всех объектов, отбрасывающих тень, независимо от того, в какую карту теней они должны быть визуализированы. Специфические преобразования разбиения будут применяться в геометрическом шейдере вместо того, как это делается на рисунке 10-11.

clip_image006

Иллюстрация 10-11 GPU конвейер рендеринга в геометрическом шейдере, Дублирующий метод.

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

Код геометрического шейдара показан в листинге10-9, где мы запускаем цикл по каждому разбиению, которое будет визуализировано - то есть, выполнено от firstSplit до lastSplit. В этом цикле мы преобразовываем каждую вершину с соответствующей матрицей сжатия разбиения. Также устанавливаем индекс объекта рендеринга, и, наконец, выводим преобразованную вершину как новый треугольник. Отметим, что выполняющийся целевой индекс фактически определен в вершину, но только значение в ведущей (первой) вершины фактически имеет отношению к делу.

Пример 10-9. Код геометрического шейдера для визуализации карт теней

clip_image008

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

Для ясности реализация, решение, что мы предлагаем, использует отдельные преобразования для всех матриц. Заранее умножая матрицы представления/проекции/сжатия вместе, мы можем осуществить схему разбиения PSSM (m) используя этот метод таким образом, что число преобразований (1 + m) на вершину. Таким образом, каждая вершина преобразована с помощью матрицы мира (один раз) и затем с помощью матриц представления/проекции/сжатия (m. раз). Стандартный рендеринг теневой карты с подобной установкой использовал бы (m + m) преобразований. Однако, если мы заранее умножаем мировые матрицы также, число преобразований одинаковое равное (m) для обоих методов. Преимущество геометрического шейдера дублирующим методом состоит в том, что проводит API наверх – запросы дополнительной прорисовки, выполнение целевые выключатели, и так далее удалены, потому что мы представляем каждому каждый предмет, отбрасывающий тень лишь однажды.

Использование техники создания экземпляров.

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

Это означает, что мы можем использовать создание экземпляров, чтобы дублировать нашу геометрию для каждого разбиения, и вычислить индекс разбиения из индекса экземпляра. Затем мы можем выполнить преобразование матрицы сжатия в вершинном шейдере так, чтобы единственная задача, ушедшая в геометрический шейдер, устанавливает целевой индекс визуализации, как показано в листинге 10-10 и представленный на рисунке 10-12.

clip_image010

Иллюстрация 10-12 GPU конвейера рендеринг в методе экземпляров

Чтобы выполнить с приведением в качестве примера, мы должны назвать функцию DrawIndexedInstanced () с числом множества экземпляров класса к lastSplit - firstSplit + 1. Это - единственное изменение, необходимое на стороне центрального процессора; это не необходимо, чтобы установить любые дополнительные потоки вершины.

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

clip_image012

Используя этот метод, мы снова удаляем дополнительный API наверху. Однако, число преобразований - то же самое, как со стандартным рендерингом теневой карты. Метод создания экземпляров может быть быстрее, чем использование дублирование геометрических шейдеров, потому что увеличение количества данных с геометрическими шейдерами может быть дорогим с точки зрения ресурсов.

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

Синтез Теней

Процесс рендеринга теней является почти тем же самым как в DirectX 9. Основное различие находится в осуществлении выборки массива текстур. Чтобы работать традиционным способом, мы можем использовать функцию SampleLevel (), чтобы произвести выборку от данной текстуры массива.

Использование этой функций является прямым, но отметим, что второй параметр - float3, где первые два float для UV координат, а третий float для индекса текстуры. mipmap уровень определен в третьем параметре функции.

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

Использование Кубических карт

HLSL 4 предлагает новую функцию, названную SampleCmpLevelZero (), которая выполняет выборку и сравнение одновременно. Она может также использоваться с линейным фильтром сравнения, чтобы получить PCF, что означает, что функция возьмет четыре выборки, сравнит каждую отдельно, и затем билинейно отфильтрует результаты.

К сожалению, SampleCmpLevelZero () не может в настоящее время использоваться с Texture2DArrays. Но может использоваться с TextureCubes. TextureCubes обычно используются для кубических карт, но они, по существу, массив текстуры с шестью текстурами, одна для каждой грани куба.

Это означает, что мы можем использовать TextureCube для шести разбиений. Использование TextureCube требует только нескольких изменений в установке, как показано в листинге 10-11. Рендеринг карт теней работает как прежде.

Осуществление выборки немного сложно тем, что обращение к карте куба происходит на со стандартными координатами текстуры, но вместо этого с вектором, указывающим на грань куба. Этот куб - куб модуля, и он центрирован в начале координат. Грани упорядочены так, чтобы от 0 до 5 индексов массива, грани были расположены в +x,-x, +y,-y, +z, и-z, соответственно. Следовательно, можем определить правильный вектор направления того, как обращаться к каждой грани, как показано в листинге 10-12.

Однако, подход, показанный в листинге 10-12, не является обязательным, потому что мы можем разделить различные случаи на три массива поиска, как показано в листинге 10-13, что немного увеличивает производительность пиксельного шейдера.

Другая проблема - то, что режим адресации выделяющего цвета не может использоваться, потому что границы просто отображены на другую грань карты куба. Однако, мы можем моделировать метод адресации выделяющего цвета, избегая процедуры выборки в целом, если координаты вне действующего диапазона координат текстуры. Это также показано листинге 10-13.

В наших испытаниях, используя SampleCmpLevelZero () с TextureCube немного улучшил нашу производительность по сравнению с использованием Texture2DArray с PCF с четырьмя отводами, осуществленным в пиксельном шейдере(приблизительно 25 команд). Однако, с TextureCube, шесть текстур будут всегда распределены, даже если необходимо меньше, часто приводя к потраченной впустую памяти.

Пример 10-11. Изменения, необходимые для того, чтобы создать TextureCube
clip_image014
Пример 10-12. Выбор Faces от TextureCube

clip_image016

Пример 10-13. Код пиксельного шейдера для синтеза теней с TextureCube

clip_image018

10.4 Дальнейшая Оптимизация

Чтобы улучшить теневое качество с PSSMs, используйте следующую оптимизацию:

· Техники фильтрации. Более близкая к проценту фильтрация (PCF) помогает сглаживанию в отображении тени, выполняя множественные испытания глубины на каждый пиксель, который заставляет теневые границы выглядеть значительно более гладкими. Карты тени дисперсии (VSMs) (Donnelly и 2006 Lauritzen) обрабатывают теневые элементы текстуры карты как распределение глубин и представляют это распределение таким образом, что оно может быть линейно фильтровано. Неравенство Чебышева используется, чтобы аппроксимировать окклюзию по произвольной области фильтра.

· Упаковка Текстур. Вместо того, чтобы сохранять PSSMs во множественные текстуры в ускоренных аппаратными средствами реализациях, пользователи могут упаковать их в единственную текстуру. Это - возможное решение, когда немного сэмплеров текстуры доступны. В Технологии DirectX 10, вместо этого могут быть использованы массивы текстур.

· Алгоритмы Деформирования. Интересное приложение схемы разбиения – применение алгоритмов деформирования (например, PSMs, LiSPSMs) отдельно в частях разбиения.

· Изменение Разрешающей способности Текстуры. У всех теневых карт в нашей текущей реализации PSSMs одна и та же разрешающая способность. Чтобы привести необходимое потребление текстур, пользователи могут корректировать размер каждой теневой карты в различных уровнях разбиения.

· Линеаризованное Распределение Глубин (Brabec и др. 2002). Использование линейного показателя глубины вместо стандарта, спроектированного z увеличения точности дискретного квантования глубины для точечных источников света.

10.5 Результаты

clip_image020

Иллюстрация 10-13

clip_image022

Иллюстрация 10-14

clip_image024

Иллюстрация 10-15

clip_image026

Иллюстрация 10-16

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

10.6 Заключение

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

В этой главе мы представили две ускоренных аппаратными средствами методики: частично ускоренная реализация на DirectX9 GPUs и полностью ускоренная реализация на DirectX 10 GPUs.Дополнительные проходы визуализации, требуемые для того, чтобы синтезировать тени, избегают в частично ускоренной реализации. В DirectX 10 конвейерах рендеринга для полностью ускоренной реализации приведена стоимость дополнительных проходов, для того, чтобы выполнить и теневые карты и тени сцены.

Есть много других способов улучшить производительность и теневое качество в нашей методике PSSMs, но одна вещь является бесспорной: С быстрым развитием GPUs PSSMs - перспективный подход для высококачественного теневого рендеринга.

Демонстрационные версии с полным исходным текстом могут быть найдены на сопроводительном DVD. Включены все три методики реализации, представленные в этой главе.

Комментариев нет:

Отправить комментарий