Наше комьюнити:   OpenGL Shader Lab  •  Half-Life FX  •  Форум  
OpenGL Shader Lab

Просмотр комментариев

Показаны комментарии 1-0 из 0

Графика 3D-игр 31-05-2009 16:34

Этот вводный доклад по 3D-графике я делал в ноябре 2007 года на «Слете джедаев». Возможно, этот материал поможет новичкам. К докладу прилагается презентация в формате Power Point, ее можно скачать в разделе Downloads. Каждый пронумерованный абзац соответствует слайду презентации.

Ссылка на презентацию: Прикрепленный файл

1
Несмотря на то, что компьютеры уже давно умеют просчитывать высококачественные изображения, где трехмерные объекты обладают огромной детализацией, где освещение, тени и атмосферные эффекты рассчитываются строго по законам физики, - проблема переноса мира реального в мир виртуальный, компьютерный, до сих пор стоит довольно остро. Особенно это касается программ, выполняющих расчеты в реальном времени, например 3D-игр. Современное оборудование не позволяет визуализовать миллионы объектов с огромным количеством деталей, со строгим учетом всех физических законов – на это уходило бы очень много времени, в то время как человек в силу физиологических особенностей будет воспринимать «реальным временем» такую частоту перерисовки, которая не ниже 25 кадров в секунду. Это и хорошо, и плохо одновременно: хорошо тем, что достаточно перерисовывать картинку только каждые 40 миллисекунд, что современное оборудование вполне позволяет, а плохо тем, что за эти 40 мс можно выполнить далеко не все сложные расчеты, требующиеся для приближения изображения на экране к реальности. Разработчики игр идут двумя путями:
 

  1. ориентация на более производительное аппаратное обеспечение
  2. упрощение используемых алгоритмов с минимальной потерей качества


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

2
Все трехмерные объекты виртуального мира строятся из треугольников. Компьютер не умеет рисовать криволинейные поверхности. Причина в том, что экран монитора состоит из точек (пелов, или пикселов), и любой объект на мониторе состоит из конечного числа точек. А значит, любая окружность будет выглядеть многоугольником с большим числом сторон. Поэтому любая криволинейная поверхность все равно разбивается на треугольники (чем больше их число, тем более «криволинейной» она кажется). Трехмерный объект, таким образом, состоит из точек – вершин треугольников (vertex), соединяющих их ребер (edge) и собственно поверхностей треугольников – граней (face). Иногда эти грани называют полигонами. Не следует путать вершины и грани объекта и его визуализируемого представления – так, у куба 6 граней, но визуализируется 12 (по 2 треугольника на каждую грань). Далее трехмерный объект с помощью определенных преобразований превращается в двухмерную проекцию на плоскость экрана, по сути – в набор пикселей. Эти пиксели иногда называют фрагментами, чтобы отличать от собственно экранных пикселей. Вообще говоря, задача визуализации сводится к тому, как представить набор трехмерных объектов на плоском экране в виде пикселей правильного цвета. На первый взгляд задача кажется несложной, но если мы задумаемся, как много факторов влияют на цвет конкретной точки в реальном мире, оказывается, что задача очень сложна. Поэтому в графике реального времени пользуются некоторыми принципиальными упрощениями. Один из примеров такого упрощения – использование текстур. Текстура – это массив цветов, который сохраняет цвет объекта в определенной точке, чтобы потом не нужно было рассчитывать его в реальном времени. И все было бы хорошо, если бы игры демонстрировали нам статичную картинку. Но объекты и сам персонаж обычно двигаются, меняется освещение – и все это должно отражаться на экране. Поэтому текстуры смогли решить проблему только частично.

3
Вот так в общих чертах выглядит трехмерный графический конвейер. На вход поступают информация о вершинах и гранях, текстуры и вспомогательная информация (например, положение источника света и наблюдателя), на выходе получается набор фрагментов, которые и выводятся на экран. Представьте, что все эти операции нужно выполнять не реже чем раз в 40 мс, а лучше еще чаще! А ведь в игре есть еще и физика, искусственный интеллект, звук и музыка…
Довольно быстро видеокарты взяли на себя работу по обработке и выводу двумерной графики. Но потом появились и первые 3D-ускорители, которые выполняли некоторые операции и с трехмерной графикой. Самым ресурсоемким для процессора оказался блок преобразования и вычисления освещения вершин, так называемый «блок Transformation and Lighting», или TnL. Эти операции удалось перенести на видеокарту, вернее на ее графический процессор (GPU). Однако этот процессор мог выполнять только набор предопределенных операций, его нельзя было программировать. Поэтому программист выбирал из ограниченного числа предопределенных операций, что будет происходить с его вершинами, и мог изменять параметры, но не сам алгоритм. Однако помимо скорости работы видеокарты, появлялась и новая аппаратная функциональность. Как программист может использовать это в своих программах?

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

  1. OpenGL содержит в себе стандартный механизм расширений, предоставляемых разработчиком драйвера. Чтобы начать использовать новые возможности, программисту достаточно скачать новый драйвер.
  2. Direct3D периодически выходит в новой версии, которая содержит новую функциональность. Зачастую она сильно меняет API и обесценивает опыт работы с предыдущими версиями Direct3D. Чтобы начать использовать новые возможности, программисту нужно подождать, пока Microsoft соизволит разродиться новой версией своего API.


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

5
Первым программируемым блоком стал блок TnL. Программист получил возможность задавать свои собственные операции для трансформации, освещения, вычисления текстурных координат и других атрибутов вершин, что позволило легко реализовать некоторые спецэффекты (объемный туман, объемное освещение, морфинг и т.д.). При этом удалось перенести некоторые вычисления с центрального процессора на графический, таким образом освобождая CPU для других дел. Небольшие программы, написанные на специальном ассемблероподобном языке, загружаемые в память GPU и выполняемые непосредственно на нем, иногда называются шейдерами. Программы, выполняющиеся в программируемом TnL-блоке GPU, называются вершинными программами, или вершинными шейдерами. Главное преимущество таких программ – это возможность задания собственных, более сложных и разнообразных алгоритмов, выполняющихся аппаратно. Архитектура GPU позволяет обсчитывать несколько вершин за раз, таким образом программа может выполняться для нескольких вершин одновременно, что приводит к увеличению производительности. Таким образом, мы либо делаем процесс визуализации быстрее (вспомним про 40 мс!), либо освобождаем центральный процессор под другие нужды (игровая логика, физика, AI).

Что может делать вершинная программа?

  • Собственные способы трансформации, освещения и вычисления текстурных координат для вершин. Например, «мультяшное» освещение.
  • Вычисление в каждой вершине вспомогательных данных, например, используемых для бамп-маппинга.
  • Вычисление проекций теневых объемов на GPU.
  • Морфинг поверхностей под действием других объектов.
  • И т.д.


У вершинной программы есть и ограничения: она не может создавать новые вершины и удалять существующие, а также не обладает топологической информацией (грани и ребра, соседние вершины). Поэтому вершинная программа не может вычислить векторы нормали и тангента (они передаются как атрибуты вершины), но может вычислить на их основе бинормаль (T x N).
Вершинные программы – ценный инструмент в умелых руках! Неумелое их использование может привести к падению производительности. Шейдеры – это инструмент, а не панацея.

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

Что может делать фрагментная программа?

  • Комбинирование текстур по произвольным алгоритмам (сложные режимы смешивания, сплаттинг).
  • Попиксельное освещение (расчет освещения в каждом фрагменте, вместо того чтобы вычислить его в каждой вершине и интерполировать на всю грань). Такое освещение выглядит более качественно.
  • Попиксельное освещение с учетом микрорельефа – бамп-маппинг.
  • Попиксельное отражение окружающей среды и/или преломление с учетом микрорельефа.
  • Искажение текстурных координат для придания объема – параллакс и рельеф-маппинг.
  • Нестандартные модели освещения (анизотропное освещение).
  • Эффекты постобработки изображения.
  • И многое другое!


7
Выше я уже говорил об ограничениях, накладываемых вершинными программами – невозможность производить на GPU вычисления, требующие топологической информации, а так же создавать новые вершины и удалять существующие. Их удалось преодолеть с появлением еще одного программируемого элемента конвейера – геометрического процессора, заменившего собой блок сборки примитивов. Соответствующие программы называются геометрическими, или геометрическими шейдерами. Я не могу много про них рассказать, так как мое оборудование их не поддерживает и я с ними непосредственно не работал. Однако нужно подчеркнуть их особенности. Геометрическая программа получает в качестве аргумента один примитив, и возвращает один или несколько примитивов. Таким образом, она имеет возможность удалять или добавлять вершины и изменять тип примитива. В дальнейшем конвейер работает с примитивами, созданными геометрической программой, а исходный примитив отбрасывается. Примеры, где может эффективно использоваться геометрическая программа – расчет теневых объемов, создание систем частиц на GPU и т.п.

8
Итак, шейдеры – это программы на ассемблероподобных языках. Их написание представляет определенные сложности (так же, как и программирование на языке ассемблера). Но существуют и языки высокого уровня, облегчающие задачу написания шейдеров. Примеры: HLSL (Direct3D), GLSL (OpenGL), Cg. Последний язык, разработанный компанией NVidia, поддерживает как Direct3D, так и OpenGL. Он может выполнять компиляцию как на этапе разработки, предоставляя программисту код шейдера на языке ассемблера, так и на этапе загрузки шейдера на целевой системе, позволяя таким образом подобрать наиболее оптимальный шейдерный профиль. Чтобы не привязываться ни к какому конкретному API, мы в дальнейшем будем рассматривать шейдеры на языке Cg.
Пример простого шейдера на ассемблероподобном языке и на языке Cg.

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

Еще раз даю ссылку на презентацию: Прикрепленный файл


Автор: XaeroX

Новости форума
Новые статьи
Вход в систему
Имя:
Пароль:
Помнить меня

[ вход ]
[ регистрация ]
[ забыли пароль? ]

Реклама
Текущие активные пользователи: 38
В данный момент на сайте 0 участников и 38 гостей.


Наш форум: В данный момент на форуме 129 посетителей.
Временная зона GMT. Текущее время 20:46.

На основе AcademCMS v1.3
Авторское право © 2001 - 2009, Chain Studios
Техническая площадка: HLFX.Ru