?

Log in

No account? Create an account

Previous Entry Поделиться Next Entry
GPU Marching Cubes в Unity
lorendroll
Я давно искал способ повысить интерактивность виртуального мира при помощи изменяемого ландшафта. Воронки в ландшафте от взрывов в Worms3D и тоннели в марсианской почве Red Faction впечатляли еще много лет назад, но я всегда хотел видеть подобное и в других играх и в более крупном масштабе. Но увы, антураж игр по сей день остается все таким же застывшим и декоративным, хоть и прибавил пикселей в разрешении.

Существует очевидная возможность изменять геометрию ландшафта путем модификации карты высот по которой он построен. Но такой метод имеет очевидные топологические ограничения так как заперт лишь в одном изменении и поэтому годится лишь для небольших ям и насыпей. Вот когда я обнаружил в одном блоге демонстрацию геометрического шейдера, строящего сложную поверхность из поля по алгоритму marching cubes, я  почувствовал, что реализовать подобное теперь и в моих силах. Как я потом выяснил, существует фантастически крутой проект Voxel Farm который реализует именно эту технологию, создавая бесконечный процедурный измеряемый мир с фотореалистичной графикой. Но несмотря на это, попыток применения такой технологии в играх до сих пор еще нет. Первая серьезная попытка, насколько мне известно, это очень любопытный проект SOE: Everquest Next. В нем некоторые участки воксельного мира будут доступны игрокам для изменения. Однако я предчувствую, что ничего кроме декоративных изменений в игру он не привнесет, хотя и это уже большой шаг навстречу физически достоверному миру.

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

Принцип марширующих кубиков довольно прост: делим трехмерное поле плотности (где каждое значение характеризует расстояние до поверхности) на кубики, и проверяем для каждого из них, не принимает ли поле внутри кубика значение, соответствующее уровню поверхности. Для этого проверяются значения плотности во всех вершинах куба, и если значения на вершинах какого-то ребра оказываются по обе стороны от уровня поверхности, значит она пересекает данное ребро куба. Далее по заранее вычисленному трафарету (в котором записаны все 256 возможных случаев пересечения ребер) выбирается конфигурация поверхности, проходящей через данный воксель. Это создает до пяти полигонов внутри него, которые и выводятся как результат.

Спасибо NVIDIA за бесценные уроки и примеры реализации этого алгоритма на GPU. Оставалось его реализовать в Unity, используя Compute Shader'ы. Это потребовалось мне для того, чтобы вывести информацию о вершинах в область памяти, доступную центральному процессору, рассчитывающему коллизии и физику тел. Обычный геометрический шейдер, реализацию которого я встретил в сети, для такого трюка годился плохо. Затем я добавил разбиение пространства на мега воксели, «чанки», чтобы создавать поле в любом объеме, и написал модификаторы поля для воздействия на него. Получилось вот так:

Однако что меня сейчас беспокоит, так это существование гораздо более оптимальных вариантов данного алгоритма. Я уже воспользовался советом из статьи от NVIDIA и избавил алгоритм от генерации повторных вершин для соседствующих треугольников. Однако само построение поверхности на монотонных участках поля (плоскости) создает множество ненужных треугольников. В сети я обнаружил информацию об улучшенных вариантах алгоритма: macet, повышающий качество репрезентации объекта путем трансформации граней воксельной сетки перед проходом mc, и dual marching cubes, создающий адаптивную сетку для деталей поля разных масштабов. Мои попытки понять до конца их принцип пока не увенчались успехом, но мне страстно хочется добиться сходных результатов. Потому что сейчас поверхность хоть и выглядит сносно, имеет огромное количество лишних полигонов и "тощих треугольников", создающих ступеньки и уродливые тени... Особенно интересен двойной marching cubes который подразумевает рекурсивное построение октодерева, адаптивно разделяющегося на участках с высокой неоднородностью поля, и подобное стандартному мс применение трафарета к построенным ячейкам, топологически идентичным кубу...

В качестве бонуса осилившим этот текст до конца, выкладываю проект Unity для построения поверхности из поля по алгоритму марширующих кубов, использующего GPU: https://dl.dropboxusercontent.com/u/4986831/Unity/GPUVOX.rar (требуется поддержка SM5.0 то есть DX10.1 и выше). Буду рад если кто-то сочтёт это полезным и пойдет вместе со мной по проторенной теоретиками, но еще не освоенной практиками дороге.

  • 1
Добрый день, наткнулся на Ваш блог, а точнее на статью, где Вы описываете Marching Cube. К сожалению проект корректно запустить не удалось, чтобы проверить.

1

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

>>"Вот когда я обнаружил в одном блоге демонстрацию геометрического шейдера, строящего сложную поверхность из поля по алгоритму marching cubes, я почувствовал, что реализовать подобное теперь и в моих силах"

А я поделал 2Д тайлинг сначала, потом попытался перенсти это в 3Д и понял что у меня наконец ватает мозгов чтобы победить MC :).

Вы кстати ориентируетесь на VoxelFarm а я больше на Blockscape, поскольку Йенс пилит свой движок на XNA и C#, что несколько ближе к Unity :).

  • 1