10 октября 2021 10.10.21 6 2964

Как устроены игры. Часть 1: 3Д

-1

Вступление

В первую очередь эта статья рассчитана не на тех, кто хочет заниматься 3д, а на обычных геймеров, которые хотят немного лучше понять как устроен процесс разработки игры. На мое решение создание такой рубрики на СГ в большей мере повлияло закрытие YouTube-канала XYZ (они еще выпускают какие-то ролики, но с разработкой они не сильно связаны). Возможно все, о чем будет написано ниже вам известно, и я зря потратил 2 часа.

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

Термины

Возможно, некоторые из вас совсем не слышали о «внутреннем мире» 3д и вообще не шарят за всякие, грани, карты нормалей, материалы и т. д. Специально для них я составил небольшой перечень основных понятий, о которых дальше пойдет речь.

  • Мэш — серая моделька без текстур.
  • Текстура — просто картинка, которая накладывается на 3д-модель.
  • Карта нормалей — штука, с помощью которой можно делать «фейковый» объем (подробнее я о них расскажу дальше).
  • Материал — говорит компуктеру как отображать текстуру. Зеркальность, шероховатость и другие подобные вещи задаются в настройках материала.

Этап 1. Моделирование.

В самом начале 3d-artists (3дшники) берут и в специальных программах создают мэш.

гифку украл. Вот источник: полезная статья про 3д
гифку украл. Вот источник: полезная статья про 3д

Есть два основных способа это сделать (создать мэш):

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

Второй способ похож на лепку из пластилина и зовется скульптингом. «Скульпторы» добавляют на модель кучу полигонов, за счет чего могут, собственно говоря, «лепить» 3д-модели.

Этап 2. Ретополигия и запекание нормалей.

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

Такую модель вы не сможете запихнуть в свою игру никаким образом, так как на ней слишком много полигонов (несколько миллионов) и компьютер будет слишком долго их все обрабатывать. В таких случаях ты садишься и делаешь так называемый «ретоп». В итоге нам нужно получить модель с адекватным (20к — 80к) количеством полигонов. Вкратце это делается примерно так:

Шаг 1. Берем нашу модель после скульптинга. У нее есть своя полигональная сетка. Дальше мы берем и создаем поверх нее новую сетку только с нормальным количеством полигонов. Например, у вас есть модель, у нее есть довольно гладкая поверхность, эта плоская поверхность состоит из 1000 полигонов. Так как плоскую поверхность можно описать пятью-шестью полигонами, мы берем и заменяем эти 400 полигонов пятью-шестью новыми полигонами. Вот примерно так это выглядит на примере 3дшного деда:

вот эти квадратики, из которых состоит дед, и есть полигональная сетка.
вот эти квадратики, из которых состоит дед, и есть полигональная сетка.

Шаг 2. Берем нашу высокополигональную модель, берем нашу, только что созданную, лоуполи модель и запекаем карту нормалей (и возможно displacement map). С помощью карты нормалей можно перенести мелкие детали, без надобности создавать для них отдельные полигоны. То есть морщины на лице деда в игре будут существовать только благодаря карте нормалей.

На скриншоте выше показан материал (слева) и его составные части (справа). Первые три части на картинке справа — это карта нормалей, color map и displaysment map. Color map говорит в какой части модели какой цвет отображать, с помощью displacement map добавляются большие выпуклые детали (такие как выпуклые кирпичи), а с помощью normal map создаются мелкие неровности (в данном случае шероховатости, неровности и сколы на кирпичах)

Важно понимать что normal map и displacement map отличаются по своей сути. Как именно?

Вообще сначала нужно объяснить как происходит обработка изображения перед тем как оно выведется на монитор. В любой сцене (будь то локация в игре или окно в 3д-редакторе) существует источник света (без него будет полная темнота на выходе). Из этого источника во все стороны выходят лучи (типа света). Эти лучи перед тем как попасть в камеру (в жизни тоже мы видим только то, что отразило от себя солнечные лучи, которые потом попали нам в глаз) встречают некоторые объекты. У разных объектов разная поверхность, и луч по-разному одних отражается. За счет этого и происходит обработка изображения. У всех 3д-объектов также есть нормали которые и говорят лучу света как отражаться от той или иной поверхности. Вот как это работает:

Без использования normal map нормали плоскости направленны перпендикулярно ей.
Без использования normal map нормали плоскости направленны перпендикулярно ей.

И normal и displacement map нужны для того чтобы добавить детализации модели. Но normal map работают за счет, так называемого, фейкового смещения, а displacement map за счет истинного смещения. Начнём с истинного смещения (displacement map). В нем изменяются положение вершин объекта, за счет чего лучи начинают по разному отражаться. В фейковом смещения (normal map) не происходит никаких изменений геометрии. Почему же при использовании normal map, свет все равно начинает отражаться в разные стороны? Normal map изменяет направление нормалей плоскости, поэтому свет начинает отражаться по-другому.

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

Есть еще много других карт, но делают они примерно тоже самое — добавляют детализацию объекту.

Если нечего не поняли, то вот статья.

Текстуры и материалы.

Тут все намного проще. Есть у вас, скажем, модель. Вы берете и в специальной программе раскрашиваете ее.

После процесса текстурирования и экспорта у вас должна получиться текстура в формате png-изображения.

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

Пример материала в движке Unreal Engine 4.
Пример материала в движке Unreal Engine 4.

Заключение

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


Лучшие комментарии

Всё как-то совсем по верхам. Будто спешим куда-то. Минимум наглядности.

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

Отдельно непонятно, зачем одновременно displacement (который как раз в играх почти не применяется, потому что для его работы нужно увеличивать количество полигонов, либо руками, либо автоматическим subdivide, что хуже), и normal map, иммитирующий тот же эффект путём шейдинга без изменения геометрии.

И ни слова про PBR, roughness и metallic, адекватное создание материала.

В общем и целом, я считаю себя дилетантом в 3D (т.к. ничего годного за свою жизнь в нём не слепил), но даже я вижу что в статье очень поверхностные знания, которые можно получить в процессе беглого просмотра одного ролика «делаем модель для игры» на ютубе.

Если я представляю себе, что я совсем профан и не шарю, мне сразу становится интересно «а зачем уменьшать количество полигонов, если есть Nanite?» (это достаточно глубокая тема, чтобы по ней можно было отдельную статью написать о том, как хранятся и рендерятся движками разные типы моделей).
А чем первый дед на картинке про ретопологию отличается от последнего? (для наглядности не хватает полигональной сетки на первом деде)
А как выглядит один и тот же материал с разным набором карт? (Очень хорошо бы продемонстрировало то, что, собственно, делают разные типы карт).

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

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

Как не автор, на сайте же куча твоего текста, то есть кода)

Блин, коммент от автора СГ — это круто. Спасибо за замечания. На самом деле в этой статье я хотел описать самую верхушку данного «айсберга» и поэтому побоялся писать о обо все, что ты написал. В следующей статье попытаюсь лучше сочетать более подробные примеры с простотой чтения обычному человеку. Плюс еще 3д довольно сложная штука, так как если рассказывать о ней подробно, то до конца не дочитает никто.

P.S. На самом деле displacement и normal могут использоваться одновременно, но для displacement, да, нужно довольно много полигонов. Сейчас отредактирую. Еще раз спасибо за фидбек.

Читай также