четверг, 23 июля 2020 г.

Volume render, часть 2. Оптимизация

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


2D частицы

В далекие времена использовалась именно эта техника. Объем заменялся набором квадратов с текстурами и рисовалось с блендингом. Такой способ использовался для облаков, дыма, взрывов и тд.
Как выглядят облака на билбордах (Mesh Viewer в RenderDoc)

Преимущества:
  • Самый быстрый способ рисования из перечисленых здесь. Производительность масштабирауется за счет количества частиц (билбордов).
Недостатки:
  • Не совместимо с VR. На большом расстоянии это не проявляется, но вблизи объемность не чувствуется.
  • Сложно делать физически корректное освещение.
  • Требуется сортировать билборды.
  • Объем выглядит слишком "сферическим", нет мелких деталей, нет форм образованных турбуленцией.
  • Анимация делается за счет движения частиц, что выглядит не очень реалистично.

3D частицы

В статье Sparse Procedural Volumetric Rendering используют частицы - сферы с наложенными на них кубическими текстурами со картой высот, освещение расчитывается отдельным проходом, сами частицы требуется отсортировать относительно камеры.  

Преимущества:
  • Различные формы частиц позволяют создавать разнообразные формы.
  • Можно комбинировать с детальным шумом для большей детализации, можно упростить интегрирование и уменьшить количество частиц для увеличения производительности на слабом железе.
Недостатки:
  • Разнообразные карты смещений, ускоряющие структуры, 3D текстуры метавокселей занимает много памяти.
  • Требуется сортировать частицы.
  • В демо присутствуют артефакты в тени от дыма, неизвестно можно ли от них избавиться.
  • Все еще есть "сферичность" из-за формы частиц.
  • Анимация делается за счет движения частиц, что выглядит не очень реалистично.

Темпоральные техники для маршинга

В статье The Real-time Volumetric Cloudscapes of Horizon: Zero Dawn предлагают каждый кадр рисовать только 1/16 часть облаков и комбинировать результат с предыдущими кадрами. Это хорошо работает для облаков в шутерах, но дает артефакты при быстром движении внутри объемов.
Объемные облака в UE4. В центре видны артефакты, когда не получилось восстановить значение пикселей из предыдущих кадров.

Скриншот из видео

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


Использование SDF для пропуска пустых областей при маршинге

Все тот же маршинг, но для объема генерируется 3D текстура с signed distance field в низком разрешении. Таким способом уменьшается количество шагов маршинга за счет нефиксированного шага, но требует перестраивать SDF при анимации и других изменениях в объемах, что занимает не мало времени (200мс как написано в статье).

Изображение взято из статьи Rendering volumetric clouds using signed distance fields


3D текстуры

В статье The Real-time Volumetric Cloudscapes of Horizon: Zero Dawn для оптимизации предлагается использовать 3D текстуры с затайленым шумом: 128^3 RGBA8 perlin-worley шум для низкой детализации, 32^3 RGB8 worley fbm шум для высокой детализации и 2D RGB8 текстура с curl шумом для имитации турбулентности. Такой способ используется во многих современных играх.

Преимущества:
  • Во много раз быстрее, так как нет вычислений шумов в шейдере.
  • Минимальный расход памяти - только на 3D текстуры шумов. В некоторых реализациях обходятся и меньшим количеством текстур.
  • Поддерживает анимацию (эволюцию) за счет смещения текстурных координат.
Недостатки:
  • Появляется заметный паттерн тайлинга.
  • Формы задаются внутри одного шейдера, поэтому увеличение разнообразия ведет к снижению производительности.
  • Стандартные артефакты при маршинге объемов - пропуск мелких деталей, нестабильные границы объемов, слоистоть, нехватка шагов маршинга. Это решается например темпоральными техниками.
  • В статье такой способ используется для рендеринга облаков при виде с земли. При приближении детализация не увеличивается, при отдалении (например при виде из космоса) детализация не уменьшается. Также при отдалении увеличивается нагрузка на память и появляются кэш промахи. Проблема решается увеличением разрешение текстур шума вблизи и генерацией мипуровней для маршинга с большим шагом.
Слева - вид вблизи, в центре и справа - на расстоянии от объемов, видно, что без мипуровней нагрузка на кэш текстур уменьшается, а на глобальную память увеличивается.


Другой способ - использовать готовые 3D текстуры, но они расходуют много памяти и не дают большого разнообразия форм, как процедурная генерация.


Sparse Voxel Octree

Как и вариант с SDF позволяет заранее обнаруживать пустые области и пропускать их. Построение SVO требует время, нужно большое количество сэмплов на воксель, чтобы не пропустить мелкие детали. Анимация формы объемов требует перестроения всего SVO, что очень медленно, а вот анимация детального шума требует только частичного перестроения, что намного быстрее.
В отличие от других способов здесь для каждого вокселя можно хранить дополнительную информацию: предрасчитанное освещение, импостеры и тд.


Задавать объемы геометрией

Для этого используется per pixel linked list - каждый треугольник атомарно добавляется в связаный список для каждого пикселя, после чего в вычислительном шейдере они сортируются и рассчитывается объем внутри геометрии. На современном железе использование атомарных операций достаточно быстрое и нагрузка на фрагментный шейдер минимальна. На GTX 1070 в FullHD рисование без прозрачности и с PPLL дает одинаковую производительность, только на 4k разрешении производительность PPLL немного отличается от обычного рисования геометрии.

60 млн треугольников в 4k разрешении рисуются с 30fps на GTX 1070

Преимущества:
  • Пустые области пропускаются намного эффективнее.
  • Границы объемов всегда четкие, нет зависимости от шага марщинга и положении камеры.
  • Можно использовать теселляцию для сглаживания геометрии или совместно с картами смещений (displacement map).
  • Можно добавить маршинг при рисовании геометрии, либо позднее - после сортировки и нахождения границ объемов.
  • Хорошо подходит для твердых объектов и жидкостей (стекло, вода и тд).
  • Позволяет комбинировать разные объемы, делать объемы внутри объемов, в отличие от маршинга, где все объемы должны быть заданы в одном шейдере.
  • Старые видеокарты и встроеные (типа Intel 630) намного лучше справляются с геометрией, чем с долгими циклами в шейдере.
Недостатки:
  • Расходуется много памяти.
  • Сложные случаи - объем отсекается передней или задней плоскостью.
  • В отличии от объемов заданых функцией или 3D текстурой здесь нет информации до ближайшей границы, есть только градиент на пути луча, поэтому рисование тумана и облаков требует дополнительных данных.
  • Сложно делать анимацию.
  • Не избавляет от необходимости делать маршинг внутри объема для интегрирования, но интегрирование можно упростить для слабых видеокарт.


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

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