Ад визуализации 1.1 — Книга 1: Обзор

в 14:07, , рубрики: game development, Gamedev, how it works?, Программирование, Работа с анимацией и 3D-графикой, разработка

Ад визуализации 1.1 — Книга 1: Обзор - 1

Недостаток знаний иногда может оказаться достоинством, потому что вы наивно говорите себе: «Пфф… разве это сложно?» и просто погружаетесь в проблему с головой. Я начал эту статью с размышления: «Хм… Что же такое Draw Call?». За время «5-ти минутного» исследования я так и не нашел удовлетворяющего меня объяснения. Я проверил часы и, так как до сна оставалось еще 30 минут, сказал…

Пфф… Разве это сложно написать самостоятельно?

… и просто начал. Это было два месяца назад и с тех пор я непрерывно читал, писал и задавал много вопросов.

Это было самое сложное и низкоуровневое исследование, которое я когда-либо делал, и для меня непрограммиста это был кошмар состоящий из «да, но в этом особом случае...» и «зависит от реализации API...». Это был мой личный ад визуализации, но я прошел через него и принес нечто с собой: Четыре книги, каждая из которых представляет собой попытку объяснить одну из частей визуализации с точки зрения художника. Я надеюсь, что вам понравится.

Ад визуализации 1.1 — Книга 1: Обзор - 2

Сегодня художники должны быть хорошо подкованными: С точки зрения компьютера ваши игровые ресурсы — это всего лишь наборы вершин и данных текстур. Преобразование этих сырых данных в изображение уровня «следующего поколения» преимущественно делается вашим центральным процессором (CPU) и графическим процессором (GPU).

1. Копирование данных в оперативную память для быстрого доступа

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

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

2. Установка Render State значений

Render State — это некоторое глобальное определение того, как полигональная сетка должна быть визуализирована. Она содержит в себе информацию о:

«вершинных и пиксельных шейдерах, текстурах, материалах, освещении, прозрачности итп. […]» [Real-Time Rendering: стр. 711]

Важно, что каждая полигональная сетка, которую CPU передает в GPU для отрисовки, будет отображена с этими условиями! Вы можете рисовать камень, стул или меч — все они будут использовать одинаковые параметры визуализации (такие как материал), если вы не измените Render State до отображения следующей сетки.

После того, как подготовка будет окончена, CPU наконец-то может обратиться к GPU и сказать, что следует рисовать. Эта команда известна как Draw Call.

3. Draw Call

Draw Call — это команда отображения одной полигональной сетки. Она отдается центральным процессором. Ее получает графический процессор. Команда указывает только на полигональную сетку, которую надо отобразить, и не содержит никакой информации о материале, так как она уже определена через установку Render State. В этот момент полигональная сетка находится в памяти графической карты (VRAM).

После того, как команда отдана, GPU берет параметры Render State'а (материал, текстуру, шейдер, ...) и все данные о вершинах и преобразует эту информацию с помощью некоторой магии в прекрасные (надеюсь) пиксели на вашем экране. Этот процесс преобразования называется Pipeline'ом.

4. Pipeline

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

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

Ад визуализации 1.1 — Книга 1: Обзор - 3

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

Ад визуализации 1.1 — Книга 1: Обзор - 4

Вот пример с единственным ядром GPU:

Визуализация — это просто выполнение огромного числа маленьких задач, таких как вычисление чего-либо для тысяч вершин или рисование миллионов пикселей на экране. Как минимум (хорошо бы) в 30 кадрах в секунду.

Важно иметь возможность вычислять эти вещи одновременно, а не каждую вершину/пиксель одну за другой. В старые добрые времена, процессоры имели только одно ядро и не было графического ускорения — они могли делать только одну вещь в один момент времени. Игры выглядели как… ретро. Современные CPU имеют 6-8 ядер, тогда как GPU содержат несколько тысяч (они не настолько сложны как CPU-ядра, но они идеальны для пропускания через себя огромного кол-ва вершинных и пиксельных данных).

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

Теперь мы знаем о том, что GPU может обрабатывать все параллельно. Но как насчет коммуникации между CPU и GPU? Ждет ли CPU того момента, когда GPU закончит свою работу и сможет получать новые команды?

Ад визуализации 1.1 — Книга 1: Обзор - 5

Нет!

К счастью, нет! Причина заключается в том, что такая коммуникация будет образовывать «бутылочные горлышки» (например, когда CPU не может доставлять команды достаточно быстро) и сделает параллельную работу невозможной. Решение — это список, в который команды могут добавляться CPU и читаться GPU независимо друг от друга! Такой список называется буфером команд.

5. Буфер команд

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

Тем не менее команды могут быть разными. Один из примеров — Draw Call, другим может быть изменение Render State'а.

На этом первая книга заканчивается. Теперь вы должны иметь общее представление о данных игровых ресурсов, Draw Call'ах, Render State'ах и взаимодействии между CPU и GPU.

Конец

Автор: AndreyMI

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js