Пример. Создание галактики в смешанной реальности

Перед отправкой Microsoft HoloLens мы спросили сообщество разработчиков, какое приложение они хотели бы видеть опытной внутренней сборки для нового устройства. Более 5000 идей были разделены, и после 24-часового опроса Twitter, победителем стала идея под названием Galaxy Обозреватель.

Энди Зибитс, художественный руководитель проекта, и Карим Лукцин, графический инженер команды, говорят о совместных усилиях между искусством и инженерией, которые привели к созданию точного, интерактивного представления галактики Млечный Путь в Галактике Обозреватель.

Технология

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

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

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

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

Сопутствующие ресурсы

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

Отрисовка частиц

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

Мы начали стресс-тесты с тысячами точечных частиц в различных шаблонах. Это позволило нам получить галактику на HoloLens, чтобы увидеть, что работает, а что нет.

Создание положения звезд

Один из участников нашей команды уже написал код C#, который будет генерировать звезды в исходной позиции. Звезды находятся на эллипсе, и их положение можно описать с помощью (curveOffset, ellipseSize, высота), где curveOffset — угол star вдоль эллипса, ellipseSize — это измерение эллипса вдоль X и Z, а высота — правильная высота star внутри галактики. Таким образом, мы можем создать буфер (ComputeBuffer Unity), который будет инициализирован с каждым атрибутом star и отправлять его на GPU, где он будет жить до конца работы. Для рисования этого буфера мы используем drawProcedural в Unity , который позволяет запускать шейдер (код на GPU) на произвольном наборе точек без фактической сетки, представляющей галактику:

ПРОЦЕССОРА:

GraphicsDrawProcedural(MeshTopology.Points, starCount, 1);

Графический процессор:

v2g vert (uint index : SV_VertexID)
{

 // _Stars is the buffer we created that contains the initial state of the system
 StarDescriptor star = _Stars[index];
 …

}

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

Мы попробовали различные модели и системы частиц, которые вращаются, как это.

Мы попробовали различные модели и системы частиц, которые вращаются, как это.

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

Прогрессирование системы частиц с помощью отрисовки GPU

Прогрессирование системы частиц с помощью отрисовки GPU

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

Создание движения звезд

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

Звезды быстрее перемещаются по длинной дуге, медленнее по краям.

Звезды быстрее перемещаются по длинной дуге, медленнее по краям.

При этом каждый star полностью описывается (curveOffset, ellipseSize, elevation, Age), где Age — это накопление общего времени, прошедшего с момента загрузки сцены.

float3 ComputeStarPosition(StarDescriptor star)
{

  float curveOffset = star.curveOffset + Age;
  
  // this will be coded as a “sincos” on the hardware which will compute both sides
  float x = cos(curveOffset) * star.xRadii;
  float z = sin(curveOffset) * star.zRadii;
   
  return float3(x, star.elevation, z);
  
}

Это позволило нам создать десятки тысяч звезд один раз в начале приложения, затем мы анимировали отдельный набор звезд вдоль установленных кривых. Так как все находится на GPU, система может анимировать все звезды параллельно без затрат для ЦП.

Вот как это выглядит при рисовании белых квадроциклов.

Вот как это выглядит при рисовании белых квадроциклов.

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

Алмазы вместо квадроциклов.

Алмазы вместо квадроциклов.

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

Добавление облаков

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

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

Без текстуры облака будут выглядеть именно так с непрозрачностью 2 %.

Без текстуры облака будут выглядеть именно так с непрозрачностью 2 %.

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

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

Сначала немного контекста

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

Исходный перед фильтрацией

Результат после фильтрации

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

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

x3 до полного разрешения.

x3 до полного разрешения.

Это позволило нам получить облачную часть с лишь частью первоначальной стоимости. Вместо того, чтобы добавлять облака в полном разрешении, мы рисуем только 1/64 пикселя и просто растягиваем текстуру обратно до полного разрешения.

Слева, с более высокомасштабным разрешением от 1/8 до полного; и право, с 3 высококлассными, используя мощность 2.

Слева, с более высокомасштабным разрешением от 1/8 до полного; и право, с 3 высококлассными, используя мощность 2.

Обратите внимание, что попытка перейти от 1/64 размера к полному размеру за один переход будет выглядеть совершенно по-другому, так как графические карта по-прежнему будут использовать 4 пикселя в нашей конфигурации, чтобы затенить большую область, и артефакты начнут появляться.

Затем, если мы добавим звезды с полным разрешением с картами меньшего размера, мы получим полную галактику:

Близкий конечный результат отрисовки галактики с использованием звезд с полным разрешением

Как только мы были на правильном пути с фигурой, мы добавили слой облаков, поменяли временные точки с теми, которые мы нарисовали в Photoshop, и добавили некоторые дополнительные цвета. Результатом стала Галактика Млечный Путь, наши команды по искусству и инженерам оба чувствовали себя хорошо, и он выполнил наши цели, связанные с глубиной, объемом и движением — все это без налогообложения ЦП.

Наша последняя Галактика Млечный Путь в 3D.

Наша последняя Галактика Млечный Путь в 3D.

Другие возможности

Мы открыли код для приложения Galaxy Обозреватель и сделали его доступным на GitHub для разработчиков.

Хотите узнать больше о процессе разработки galaxy Обозреватель? Ознакомьтесь со всеми нашими последними обновлениями проекта на канале Microsoft HoloLens YouTube.

Об авторах

Фотография Карима Люцина за столом Карим Люкцин ( Karim Luccin ) — инженер по программному обеспечению и энтузиаст визуальных эффектов. Он был инженером графики для Galaxy Обозреватель.
Фото арт-руководителя Энди Зибитса Энди Зибитс является арт-лидер и космический энтузиаст, который руководил командой 3D-моделирования для Галактики Обозреватель и боролся за еще больше частиц.

См. также раздел