Skip to main content

Погружение в создание Immersion

  • Эта публикация - перевод статьи. Ее автор - www.ctrl-alt-test.fr. Оригинал доступен по ссылке ниже:

Наконец. В декабре прошлого года мы наконец закончили. Это видео - наша последняя постановка, 4-минутная анимация под названием «Погружение» . Чтобы быть более точным, это захват того, что обычно называют вступлением 64 КБ. Но об этом чуть позже.

Создание заняло большую часть свободного времени двух лет. Все началось во время Revision 2015, крупного мероприятия, которое проводится каждый год в Германии, во время пасхальных выходных. Мы оба болтали в нескольких километрах от отеля до места для вечеринок, наши лица боролись с бодрым утренним воздухом и лишением сна. Прошлой ночью уровень конкуренции в 64 КБ был высоким. Действительно высокий. Давно созданная венгерская группировка Conspiracy наконец вернулась с серьезным напыщенным вступлением . Наш лучший враг Приблизительно успел за свой трехлетний цикл выпуска и показал значительное улучшение в рассказывании историй. Плодородный Меркурий теперь имел зрелый дизайн, с предвещающим интро названием, которое не оставило никаких сомнений в вскрытии.

В тот год, с пустыми руками, мы не участвовали в конкурсе, но мы, конечно же, хотели вернуться как можно скорее. Тем не менее, после такого шоу нам было интересно: приятный взгляд, великолепное повествование, великолепный дизайн… как мы можем достичь этого уровня? Я не мог понять, какая концепция, которая, даже идеально выполненная, была бы явным победителем среди этих трех. Не говоря уже о том, что наша технология была ниже любого из них. И вот мы бросали идеи на Гогенцоллернштрассе, когда, наконец, один из них застрял. Город, поднимающийся из моря. Это была концепция, которая, при правильном исполнении, может иметь шанс конкурировать на том уровне, на котором эта подгруппа этой субкультуры стала. Редакция 2016 , будьте готовы, вот и мы!

Редакция 2016 года пронеслась мимо нас с громким звуком… Ревизия 2017 года будет тогда. Увы, мы едва добрались до этого нового срока. На вечеринке, когда люди спрашивали, как идут дела, ответ был остроумным: «Нам понадобился год, чтобы сделать первую половину, я уверен, что мы можем сделать вторую половину за 24 часа» . Мы не могли. Мы выпустили, хотя, но вторая половина была срочно отправлена, и это показало. Настолько, что мы даже близко не подошли к подиуму. Но мы работали над этим, дали ему любовь, которая, как мы думали, была нужна, и наконец выпустили финальную версию, показанную выше.

Что за введение 64К?

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

Вступления размером 64 КБ, кратко 64 КБ, похожи на демонстрации, но с дополнительным произвольным ограничением размера: они должны полностью помещаться в один двоичный файл размером не более 65536 байт . Никаких дополнительных ресурсов, никакой сети, никаких дополнительных библиотек: обычное правило заключается в том, что он должен работать на только что установленном ПК с Windows с последними драйверами.

Но насколько большой это точно? Вот несколько точек сравнения. 
В файле размером 64 КБ вы можете хранить:

  • 400 мс волнового звука с качеством CD, или
  • 3 с mp3 на 192 кбит / с, или
  • Изображение 200 × 100 RGB .bmp или
  • Снимок JPEG среднего размера, среднего качества, например, скриншот 800 × 450 из вступления:
Скриншот 64 КБ

Изображение JPEG размером 65595 байт, 59 байт сверх ограничения в 64 КБ. :)

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

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

На самом деле, из-за этих экстремальных ограничений нельзя использовать обычные методы и инструменты. Вместо этого мы написали свой собственный набор инструментов, который сам по себе является интересной задачей: мы создаем текстуры, 3D-модели, анимацию, траектории камеры, музыку и т. Д. Благодаря алгоритмам, процедурной генерации и сжатию. Мы поговорим об этом очень скоро.

Некоторые цифры

Вот краткий обзор того, как расходуются эти 64 КБ:

  • Музыка: 12,4 КБ
  • Сетки: 12,5 КБ
  • Текстуры: 4,8 КБ
  • Данные камеры: 1,3 КБ
  • Шейдеры: 6,2 КБ, из 5 000 строк кода
  • Двигатель: 12,9 КБ, из 20 000 строк кода
  • Само введение: 12 тысяч строк кода
  • Потраченное время: часов, может быть, более тысячи
Перераспределение использования двоичного пространства

Эта диаграмма показывает, как 64 КБ используются другим типом контента после сжатия.

Эволюция двоичного размера

Эта диаграмма показывает, как развивался двоичный размер (исключая ~ 2 КБ депакера) до финального выпуска.

Дизайн и вдохновение

Согласившись, что центральной темой был затопленный город, один из первых вопросов был: как этот город будет выглядеть? Где он был расположен, почему он был затоплен, какова его архитектура? Один простой ответ обратился ко всем этим пунктам: это мог быть легендарный затерянный город самой Атлантиды . Это также объясняет и оправдывает возникновение: его божественной природой (буквально deus ex machina). И так было решено.

Концепт-арт Атлантиды

Ранний концепт-арт для возникшего города. Произведения искусства, представленные в этой статье, были созданы Бенуа Молендой.

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

Концепт-арт городских деталей
Концепт-арт других городских деталей

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

Поиск справочного материала для Artemision оказался неожиданным, обогащающим опытом. Первоначально мы искали только фотографии, схемы или карты для справки. Но когда мы узнали о названии «Джон Тертл Вуд», все стало гораздо глубже. Вуд был тем человеком, который отвечал за поиски и окончательное открытие места расположения храма. Надеясь, что его имя даст лучшие результаты, чем просто «Artemision», мы продолжили, и мы немедленно нашли книгу, которую он написал в 1877 году, в которой он сообщает не только описания и рисунки храма, но и его одиннадцатилетний путь, чтобы найти потерянный участок, его переговоры с Британским музеем о финансировании, его отношения с местными рабочими и вовлеченная дипломатия до случайного рытья ям.

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

Храм Дианы - План
Незавершенное производство Artemision mesh
Храм Дианы - поперечный разрез
Храм Дианы - продольный разрез

И, кстати, как должна выглядеть крыша? У некоторых представлений, в том числе у Вуда, есть дыра, а у некоторых нет; по-видимому, существует некоторое противоречие. Мы решили пойти с открытой моделью крыши, что позволило нам раскрыть интерьер храма с помощью луча света. Иллюстрации выше показывают план этажа и поперечные сечения из книги «Открытия в Эфесе» по сравнению с нашей моделью храма, находящейся в стадии разработки.

Достижение желаемого взгляда

Мы знали с самого начала, что появление воды будет иметь решающее значение для этого вступления. Поэтому мы потратили немало времени, начиная с просмотра справочного материала, чтобы понять основные элементы подводного вида. Возможно, вы догадались, что вдохновили Джеймса Кэмерона Бездна и Титаник3DMark 11 или «Бегущий по лезвию»  Ридли Скотта для освещения.

Правильный взгляд не сводился к реализации и включению какой-то эпической функции MakeBeautifulWater () . Вместо этого это была комбинация ряда эффектов, которые, когда они были усовершенствованы, в конечном итоге заставили нас, зрителя, принять иллюзию и чувство «Вот оно, мы под водой!». Но одна ошибка, и обман рухнет; урок, который мы усвоили слишком поздно, когда в комментариях после первоначального релиза указывалось, куда исчезла иллюзия.

Концепт-арт сцены старта
Концепт-арт подводного пейзажа

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

Поверхность воды

Обелиск появления сцены

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

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

Появление сцены

Размытое изображение храма отражается на поверхности воды.

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

Объемное освещение

«Как сделать лучи света для погружного?» Был один из первых технических вопросов. Может быть, подойдет прозрачный рекламный щит с красивым шейдером? Однажды мы начали экспериментировать с наивным лучом, проходящим через среду. Мы с восхищением отметили, что даже в раннем сыром тесте рендеринга, несмотря на цвета кодера и отсутствие приличной фазовой функции, объемное освещение было сразу убедительным. В тот момент эта первоначальная идея рекламного щита исчезла, и о ней больше никогда не будет слышно.

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

Храмовая сцена

Легкие шахты придают этой сцене вид, вдохновленный фильмом «Бегущий по лезвию».

Пришло время превратить этот прототип в реальный эффект, поэтому мы документировали себя, читали учебное пособие Себастьяна Иллера, его презентацию DICE и другие подходы, такие как эпиполярные координаты. В конце мы остановились на более простой технике, близкой к той, которая использовалась в Killzone Shadow Fall (видео здесь), с несколькими вариациями. Эффект выполняется в одном полноэкранном шейдере с половинным разрешением:

  1. На каждый пиксель отбрасывается луч, и его пересечения с каждым световым конусом решаются аналитически. 
    Математика описана здесь (теперь угадайте, по какой причине статья была написана в первую очередь ;-)). С точки зрения производительности, было бы, вероятно, более эффективно использовать легкую ограничивающую объем сетку, но для 64k было бы проще использовать аналитический подход. Очевидно, что лучи доходят только до глубины в буфере глубины.
  2. Если луч пересекается, то объем внутри конуса затем направляется лучом. 
    Количество шагов ограничено по соображениям производительности, и они случайным образом смещаются для удаления полос. Это типичный случай обмена полос на шум, визуально менее сомнительный.
  3. На каждом этапе выбирается карта теней, соответствующая свету, и вклад света накапливается в соответствии с простой фазовой функцией Хенея-Гринштейна
    В отличие от подходов, основанных на эпиполярных координатах, используя этот метод, можно получить неоднородную плотность среды, что добавляет больше разнообразия, но мы не реализовали такой эффект.
  4. Полученное изображение повышающая дискретизация с использованием двух проходов двусторонний фильтра Гаусса и добавил в верхней части основного буфера визуализации. В отличие от учебника Себастьена, мы не используем временное перепроектирование; мы просто используем достаточно большое количество шагов, чтобы уменьшить видимые артефакты (8 шагов в настройках низкого качества, 32 шага в настройках высокого качества).
Алтарная сцена

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

Поглощение света

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

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

Код примерно следует этой логике:

vec3 lightAbsorption = pow (mediumColor, vec3 (mediumDensity * lightDistance)); 
vec3 lightIntensity = DistanceAttenuation * lightColor * lightAbsorption;

vec3 surfaceAbsorption = pow (mediumColor, vec3 (mediumDensity * surfaceDistance)); 
vec3 surfaceColor = LightEquation (E, N, материал) * lightIntensity * surfaceAbsorption;
Тест поглощения света

Испытание поглощения света в водной среде. Обратите внимание, как на цвет влияют расстояние от камеры и расстояние от источников света.

Добавление растительности

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

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

Ранний тест на растительность

Пробный снимок с несколькими редкими растениями.

Однако, когда мы попытались добавить эти растения в сцену, мы поняли, что производительность быстро увеличивается с количеством объектов. Это ограниченное количество, которое мы могли бы поместить, чтобы изображение выглядело убедительно. Оказывается, наш новый неоптимизированный двигатель уже достиг первого узкого места. Таким образом, мы реализовали грубую специальную отбраковку усеченного конуса в последнюю минуту (в финальной версии используется правильная отсечка :)), что позволило увидеть плотные кусты в демоверсии.

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

Подводная растительность

Растительность отбрасывает теневые узоры на морское дно.

Давать объем с частицами

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

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

Сцена открытия виадука в

В этом кадре частицы обеспечивают сигналы глубины и ощущение плотности при погружении в воду.

Музыка

Как разместить качественную музыку размером около 16 КБ? Эта проблема не нова, и большинство вступлений 64 КБ, написанных после .product в 2000 году, используют те же понятия. Оригинальная серия статей старая, но все еще актуальна: работа звуковой системы FR-08 .

Короче говоря, идея в том, что нам нужен музыкальный лист и список инструментов. Каждый инструмент - это функция, генерирующая процедурный звук (см., Например, Субтрактивный синтез и синтез Физического моделирования ). Нотный лист представляет собой список примечаний и эффектов для применения. Он хранится в формате, аналогичном midi, с некоторыми изменениями для уменьшения размера. Во время исполнения программы музыка генерируется.

У синтезатора также есть версия плагина ( VSTi ), которую музыкант может использовать из своего любимого инструмента. Как только музыка составлена, музыкант нажимает кнопку, которая экспортирует все данные в файл. Мы встраиваем данные в демо.

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

Даниэль Линдхольм сочинил музыку, используя синтезатор 64klang, созданный Домиником Рисом.

Рабочее окружение

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

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

Горячая перезагрузка всех данных

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

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

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

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

Настраиваемые значения

Перезагрузка данных - это хорошо, но как насчет самого кода? Это сложнее, и мы подошли к этой проблеме шаг за шагом.

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

Этот трюк ограничен, но он действительно прост и может быть интегрирован в код за считанные минуты. Более того, хотя он предназначен только для настройки констант, он все же может использоваться для целей отладки, чтобы изменить путь к коду или переключать функции с такими условиями, как if (_TV (1)) .

C ++ перекомпиляция

Наконец, нашим последним обновлением в нашем стремлении сделать код более гибким было включение инструмента Runtime Compiled C ++ в нашу кодовую базу. Скомпилировав код в виде динамической библиотеки и загрузив его, а также выполнив немного жонглирования сериализацией, он позволяет вносить изменения в этот код и видеть результат во время выполнения, без перезапуска программы или, в данном случае, демонстрации.

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

Продолжение следует

Здесь заканчивается первая часть того, что будет серией статей о методах, используемых в H - погружении. Мы хотели бы поблагодарить Алана Вулфа за чтение корректуры; Вы можете проверить его много технических статей в его блоге. В следующих частях мы представим более подробно, как создаются текстуры и сетки.

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

Часть 2. Текстурирование в введении 64 КБ.