Давайте напишем ... MMO! Часть 6: Форма мира

Опубликовано NowhereMan -

29 декабря 2010

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

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

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

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

Но прежде чем я смогу сделать видео, я должен принять некоторые решения о форме мира.

Бесконечный ... и унылый?

Я не покупал много игр за последние несколько лет. Из того, что я вижу в игровых трейлерах, мне кажется, что у там есть либо космические корабли и инопланетяне, сражающиеся в разрушенных городах, либо эльфы в лесу. Я никогда не соглашался с Роджером Эбертом, что видеоигры не могут быть искусством, но я также не был слишком вдохновлен тем, во что я играл. Графика становится настолько хороша, что мы можем рендерить практически всё, что только можем себе представить. Разве мы не можем представить что-то более интересное, чем фэнтези и фантастика 1950-х годов?

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

Не знаю, смогу ли я что-нибудь с этим сделать. Мне нравится открытость Minecraft, и то, как люди могут играть там с созданием вещей. У него очень низкие барьеры для творчества. Если я смогу сохранить этот аспект в своей системе, возможно, художники появятся и будут делать с ней по-настоящему новые вещи. Но мне все равно нужно посадить семя и где-то начать. Я не могу просто предложить пустую страницу и сказать: "Теперь создавай!". Так что общий стиль мира должен быть привлекательным.

Minecraft имеет очень большой (практически бесконечный) мир, но это все одно и то же. Еще одна скала, еще один лес, еще один пляж. Notch добавил биомов, но я действительно не вижу большой разницы. Я не хочу такой мир. Почему я не могу добавить совсем другие растения и пейзаж? Почему я не могу иметь три солнца на небе? Почему я не могу изменить силу тяжести?

С архитектурной точки зрения заманчиво иметь просто пустое пространство в 3-х измерениях. По мере того, как вы будете перемещаться в игре, база данных будет возвращать все объекты, находящиеся рядом с вами, а клиент будет их визуализировать. Это могут быть пейзажи, звезды или даже генераторы гравитации. Если вы хотите голубое небо и солнце, постройте большой шар вокруг своей местности и раскрасьте солнце и звезды изнутри. Сделайте так, чтобы она повернулась, и у вас будет цикл день/ночь. Все это может быть маленьким миром, висящим в космосе, прямо рядом с другими маленькими мирами.

У меня есть несколько оговорок с таким подходом. Во-первых, он не очень удобен для пользователя. Люди должны знать, как добраться из одного места в другое. Они должны давать друг другу указания. И они должны уметь сформировать ментальную карту места. Сказать "начни с космической станции, выйди из шлюза и ты будешь в этом торговом центре, потом выйдешь из торгового центра и окажешься в джунглях с динозаврами, потом прыгнешь в вулкан и будешь у меня дома", наверное, не очень хорошо сработает.

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

Самое главное, я хочу избежать расползания. Когда я посещал Second Life, кажется, что есть акр за акром пустующих зданий. Я понимаю желание уехать куда-нибудь и построить замок своей мечты. Проблема в том, что если все так делают, то ты никогда никого не встречаешь в мире, и никто не видит твоих работ. Я думаю, что для того, чтобы в мире появилось по-настоящему жизнеспособное сообщество, оно должно быть более многолюдным и урбанистичным. Но как удержать людей от расползания в виртуальном мире с бесконечной территорией? В безудержном пустом пространстве, о котором я только что рассказал, не будет никакого способа сделать это.

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

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

Значит, вот мой план. У меня будет мир с множеством астероидов, висящих в космосе вокруг солнца (или, может быть, нескольких солнц, для разнообразия), и на каждом из них будут вода, растения и здания. Расстояние от солнца варьируется, так что вы можете иметь огромное солнце, как я делал в демо, или крошечное. Каждая скала может иметь свой собственный погодный, гравитационный и дневной/ночной цикл (вызванный вращением скалы.) Скалы будут стационарными, так что вы сможете найти их - не будет никаких реальных орбит, а гравитация будет локальной к астероиду. Все остальное будет невозможно реализовать. Это не реалистично, но я также хочу, чтобы астероиды были достаточно близко, чтобы вы могли видеть прогресс у ваших соседей. Это заставит людей прийти и посмотреть.

Теперь мне просто нужно осуществить что-то подобное и записать это на видео!

Что мне понадобится

Сначала мне нужно сгенерировать поле астероидов и звезд в подходящих местах. Я могу сделать это с каким-нибудь источником шума и несколькими правилами. Не проблема.

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

Деревья и растения будут добавлены. Так как я не беспокоюсь о скорости рендеринга, я просто добавлю несколько тысяч. Я могу использовать клип-арт или фотографии деревьев из сети. Поиск изображений Google - мой друг.

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

Шамус Янг и его друзья создали сервер Minecraft под названием http://twentymine.com и сделали сохранения публичными. Шеймус также написал о сервере здесь. Я спросил его, не возражает ли кто-нибудь, если я вырежу из него несколько зданий. Его ответ был "Вперед". Так что я написал импортер и прихватил немного мира. На рисунке 1 изображен вид Minecraft в этой области, а на рисунке 2 показан мой демонстрационный вид.

Рис. 1: Мост и пейзаж
Рис. 2: Те же блоки, которые были нарисованы демо

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

Я действительно не хочу останавливаться и реализовывать модель освещения для этого видео. Я не понимаю, как это делается, и каждое учебное пособие, которое я читал об этом, кажется сложным для реализации. Свет - это плохо, а тени - хуже. Похоже, что в большинстве игр есть всевозможные короткие промежутки времени, чтобы дать вам немного приличного освещения, не тратя на это много времени. Даже такие игры из списка A, как Half-Life, допускают ошибки с тенями, рисуя их, например, не на той стороне стены.

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

Трассировка лучей

Рисунок 3: Тени с трассировкой лучей

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

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

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

Рисунок 4: Несколько источников света

 

Я не собираюсь вдаваться в подробности трассировки лучей. Для начала, вы можете пойти сюда. Этот код не будет использоваться в реальной системе, так что я просто расскажу.

У меня есть все координаты всех кубов в демо. Я записываю их все в файл. Трассировщик лучей читает его и получает огромный список треугольников. Я начинаю с позиции глаз. Я знаю углы виртуального "экрана", на который проецирую мир. Так что луч от глаза через пиксел - не проблема.

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

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

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

Рис. 5: Прозрачность

 

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

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

Единственная реальная проблема в том, что трассировщик лучей работает ужасно медленно. Я ничего не оптимизировал, даже не сократил количество треугольников, которые я тестирую. Даже для этих маленьких сцен с 1000 треугольниками на изображение уходит 20 секунд. Большее изображение Minecraft сверху - 240 000 треугольников. Умножьте это на 600 на 800 на 30 кадров в секунду, скажем, на 90 секунд видео, и у нас есть около 300 триллионов тестов на пересечение треугольников лучами. А на самом деле - как минимум в два раза больше, так как у нас есть луч на сцену и луч, как минимум, на солнце. Если присутствует несколько источников света, то каждый из них добавляет другой луч. И, конечно, я хочу, чтобы мир был больше, чем просто один мост и немного пейзажа.

Я знаю, что могу получить огромное ускорение, не сравнивая со всеми треугольниками на сцене. Я не уверен, что смогу получить его достаточно быстро, чтобы рендерить весь мой мир за разумное количество времени (скажем, 10 часов для 90 секунд видео). Если я смогу, то это решит все мои проблемы со светом одним махом. Мне не нужно придумывать хитроумные способы работы с освещением. Если нет, то это вернётся на чертежную доску.

Наконец, последнее, чего мне не хватает, так это кода для записи кадра изображения в какой-нибудь видеоформат. Я потратил пару часов на сортировку SDK Microsoft Media Foundation, прежде чем сдался и сделал то, что должен был сделать, - спросил Google. Он указал мне на эту страницу, в которой есть все необходимое для написания AVI-файла, включая исходный код.

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