Arseny Kapoulkine:
Advanced Visual Effects with DirectX 11: DX11 Software Tessellation.
Speaker: John Kloetzli (Firaxis)
Доклад с интересным названием от авторов Civ5 (если кто не в курсе, да)
Я значит тут сделаю лирическое отступление.
Я геймдевом начал интересоваться примерно лет 10 назад.
Примерно лет 10 назад в геймдеве вообще (или в геймдеве вокруг меня) была популярна тема ландшафтов.
Плох был тот графический программист, который не защитил диплом по рендерингу ландшафтов в реальном времени.
Не вырастил хайтмап и не родил тесселятор.
Был (все еще есть, впрочем) сайт vterrain.org, и были различные публикации.
Про то как быстро (или медленно) генерировать геометрию, которая достаточно хорошо приближает heightfield.
Потом значит люди решили что все это отстой.
И надо делать chunked LOD от господина Ulrich но без упрощения геометрии, и так сойдет.
А потом тема ландшафтов как-то сошла на нет потихоньку.
И вот значит эта презентация - в чистом виде welcome back to 2002 или когда там это все было.
Я недостаточно хорошо запомнил детали всех тех алгоритмов, но уверен что он есть - и презентация про то как этот алгоритм реализовать в 2014.
Чертовы спирали.
Итак, есть игра Civ5, там есть карта (128х128 hex tiles, на каждый тайл 64х64 heightmap), heightmap генерируется процедурно.
И на каждый тайлик есть 512х512 текстуры, текстуры тайлятся и заданы артистами.
Детализации карты высот недостаточно, но она и так получается 8k x 8k.
Хочется более детальную карту высот, без повторений, на текущих GPU.
Хочется на каждый тайл иметь 256х256 хайтмап - в основном чтобы моделировать острые углы (например, пики горных высот)
Ну окей, давайте использовать хардварную тесселяцию.
Проблема в том что:
  • 1. Треугольники должны быть значительно больше пикселя чтобы производительность была приемлемой - маленькие треугольники генерируют слишком много fragment processing на GPU.
  • 2. Треугольники должны быть меньше пикселя чтобы изменение уровня детализации (например, при zoom in/out камеры, или между соседними патчами разного уровня детализации) было незаметно.
В итоге если каждый патч тесселировать в зависимости от его screen space ошибки, то получается очень много мелких треугольников.
Хочется иметь мелкие треугольники там где есть высокочастотные детали в heightmap и не иметь их там где их нет, поэтому тесселировать надо с учетом карты высот.
Проблема в том, что разбиение ландшафта на патчи - это регулярная сетка.
Если патч слишком большой то его чрезмерная тесселяция из-за того что нужно высокое качество на одном холме приведет к куче мелких треугольников.
Если патч слишком маленький то будет много геометрии потеряно на границе между патчами.
В идеале надо иметь очень локальный алгоритм - генерировать много геометрии рядом с острыми пиками.
Но только там.
Ну что, давайте собирать quadtree.
Идея примерно та же что в shadow maps в треде выше, ну и наверняка не в новинку тем кто 10 лет назад работал с ландшафтами...
Есть ландшафт, он разбит на крупные тайлы, когда тайл становится видимым - надо для него сгенерировать геометрию.
Для этого сначала мы с помощью CS и всяких шаблонных текстур и прочих шумов перлина генерируем full-res height map.
Для кусочка ландшафта, не для всего.
Потом мы по нему собираем геометрию - выглядит это так.
Представим себе сетку полного разрешения, и для каждого квада зададимся вопросом - насколько изменится форма ландшафта если его смержить с 4 соседями (т.е. вмержить в более высокий уровень quadtree)
Это просто разница между интерполированной высотой и реальной высотой по ряду направлений, т.е. смотрим насколько сильно изменяется силуэт ландшафта в этом месте если вместо высот.
A, B, C.
сделать высоты.
A, (A+C)/2, C.
Дальше повторяем это до посинения, в каждом квадратике получаем "важен ли он для результирующего изображения".
Потом поднимаемся на уровень quadtree выше и считаем то же самое для следующего уровня, итп.
Чтобы не было T-junctions, ограничиваем переход LOD - соседний патч должен иметь LOD отличающийся от твоего не больше чем на 1.
Я очень конспективно, это все стандартно для рендера ландшафтов.
Получается что у патча ребро может быть либо разбито посередине вершиной (если сосед более высокого LOD) или не разбито (если сосед такого же LOD)
Это всего 16 вариантов топологии, такое просто генерировать в CS.
В итоге получается стандартное квадродерево собранное по heightfield, из которого сгенерирована геометрия.
Интересный нюанс - есть два варианта тесселяции квада.
Вот такой диагональю \ и вот такой /
Если для каждого выводимого квада смотреть на данные height field и выбирать диагональ с наименьшей ошибкой - результаты сильно улучшаются.
Т.к. диагональ пытается выровняться по направлению острого хребта.
В итоге получаем меньше треугольников, рендерится все через это быстрее и качество лучше.
В демке используются indirect draw/dispatch например т.к. при генерация геометрии чанка получается неизвестное на CPU количество треугольников которые надо бы отрендерить в этом же кадре.
Вот.