НАЗАД

Статья взята с сайта computery.ru

Потомок кубика Рубика

Николай Забугорский

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

С вокселем возникли сложности. Два человека, игравшие в Comanche, сказали, что “воксель - это такой кубический пиксель”. Еще один, вспомнив статью из журнала двухлетней давности, добавил, что “тридэфиксы умеют переваривать только треугольные полигоны, а квадратные воксели выплевывают обратно”. Высказав эту умную мысль, знакомый в задумчивости повертел в руках валявшийся на столе 3D-ускоритель и пробурчал: “Не понимаю! Микросхема квадратная, воксели тоже, полигоны треугольные, но ускоряет почему-то полигоны, а не воксели…Чертовщина какая-то”.

Вот так и появилась идея написать статью, рассказывающую о воксельных и полигональных движках, их достоинствах и недостатках. При этом не сильно перегружая ее техническими подробностями, чтобы поняли не только компьютерщики, но и люди, не справившиеся с “первым_монстром_из_кваки”.

Родословная полигона

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

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

И тогда разработчики подумали: “А что, если заставить машину не просто показывать картинки, но и моделировать их самостоятельно, в реальном времени?”. Тогда и модель персонажа можно будет описать кривыми, разложить ее на составные элементы, покрасить в нужный цвет, подсветить, где надо, и шлепнуть на морду картинку. А потом вертеть эту модель во все стороны света, руки ей поднимать, носик пудрить. На такое ведь никаких спрайтов не напасешься!

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

Процесс получения изображения на 3D-ускорителе именуется “конвейер 3D-рендеринга”. Условно его можно разделить на два больших этапа: стадия построения геометрической фигуры и стадия формирования 2D-картинки, то есть непосредственно рендеринг.

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

До этого момента все операции производятся над трехмерным миром, где у каждой фигуры есть три координаты в пространстве. На экране монитора в 3D-играх мы видим как бы 2D-проекцию из определенной точки (в Quake - из глаз героя, в Tomb Raider - из-за спины). Выбрав точку наблюдения, движок, дабы не делать лишней работы, отбрасывает невидимые из этой точки примитивы и преобразовывает полученные данные в формат понятный 3D-ускорителю.

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

Достоинства полигональных движков очевидны: во-первых, простота использования - существует множество библиотек для работы с 3D-графикой (Direct 3D, Open GL, Glide). Также полигональные 3D-игры доступны для широкой аудитории - сейчас практически каждый первый игровой компьютер оснащен 3D-ускорителем. Да и быстрое развитие технологий тоже можно назвать достоинством: каждый год появляются новые алгоритмы, а современные графические чипсеты обеспечивают полное аппаратное ускорение всех этапов конвейера рендеринга.

Недостаток у полигональных движков всего один: взгляните на любой современный 3D-Action. В частности, обратите внимание на модели персонажей. Это уже не те угловатые куклы, что были в первом Quake; каждая насчитывает несколько тысяч полигонов. Но для имитации реального мира потребуется в сотни, если не в тысячи раз больше. Необходима технология, способная работать с трехмерными фигурами точно так же, как в свое время видеокарты работали с обыкновенными 2D-картинками. Иными словами, нужен трехмерный пиксель.

Помните, как я в начале статьи воксель обозвал?..

Воксельные движки

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

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

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

Окружающий нас мир изобилует мельчайшими деталями. С высоты птичьего полета морской пляж выглядит однотонным желтым куском земли. Но стоит прогуляться по нему ножками, и мы тут же заметим всякие бугорки и холмики. А если нагнуться и подобрать гальку, то каждый камешек будет иметь свою собственную, уникальную фактуру. Если же задействовать микроскоп, то... какое счастье, что в вертолетных симуляторах не бывает микроскопа! Но, даже и без него, для создания реалистичного виртуального мира потребуется очень четкая карта высот (отсчитывая по метровой шкале, для десятикилометровой оси Z мы получим 10 000 уникальных значений!). Поэтому в воксельных движках используются специальные технологии, улучшающие качество heightmap низкого разрешения. Два наиболее распространенных способа основаны на диаметрально противоположных алгоритмах: первый добавляет множество новых отсчетов в карту высот, используя псевдослучайные карты смещения (displacement maps), второй сглаживает угловатости, получая новые значения по оси Z путем интерполяции между существующими.

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

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

Движок наш с офтальмологами не знаком, поэтому считает, что человеческий глаз работает именно так, как описано в предыдущем абзаце. И поэтому рендеринг финальной картинки методом трассировки лучей происходит следующим образом: нашли самую нижнюю координату в карте высот, выпустили туда луч, натолкнулись на какое-нибудь препятствие, считали значение в карте цветов, покрасили пиксель и поднялись на один пиксель повыше. Снова пустили луч, натолкнулись на что-то твердое и т. п. Интересно, что и на этом этапе можно немножко ускорить работу движка, слегка изменив алгоритм. Предположим, пущенный луч уперся в стенку красного кубика, причем в самый низ. Следующий по счету пиксель сверху тоже будет красным, и что самое важное - будет иметь те же координаты по осям X и Y. Зачем же, спрашивается, пускать еще один луч от самого "глаза", если можно сначала подняться наверх и посмотреть, что там такое. Если стенка, то сразу ее покрасить, и снова наверх - до тех пор, пока на свежий воздух не выберемся, сиречь ничего не найдем. Вот тогда и новый луч выпустим. Недостатков у такого подхода никаких - сплошная экономия времени.

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

Сейчас на рынке представлено совсем немного игр с воксельной графикой (в основном, это авиасимуляторы). Объяснятся данная ситуация просто: воксельному движку даже самый мощный 3D-ускоритель может оказать лишь одну "медвежью" услугу - размазать пиксели к чертям собачьим. Однако уже существуют игры, сочетающие в себе как полигональную, так и воксельную графику (первыми такое проделали создатели Zar). И результат получается прямо-таки великолепный: красивые детализированные ландшафты и аккуратненькие модели с цветным освещением.

Так что будущее, как мне кажется, именно за таким вот симбиозом.

НАЗАД