16 марта 2011

Сектор Лирики / Shader (Шейдер) / Vertex Shader (Вершинный Шейдер)

Шейдером в широком смысле называется программа для визуального
определения поверхности объекта. Это может быть описание освещения,
текстурирования, постобработки и т.п. Шейдеры выросли из работ Кука
(Cook's shade trees) и Перлина (Perlin's pixel stream language). Сейчас
наиболее известны шейдеры RenderMan Shading Language. Программируемые
шейдеры были впервые представлены в RenderMan компании Pixar, там
определены несколько типов шейдеров: light source shaders, surface
shaders, displacement shaders, volume shaders, imager shaders. Эти
шейдеры чаще всего программно выполняются универсальными процессорами и
не имеют полной аппаратной реализации. В дальнейшем, многие
исследователи описывали похожие на RenderMan языки, но они уже были
предназначены для аппаратного ускорения: система PixelFlow (Olano и
Lastra), Quake Shader Language (применен id Software в графическом
движке игры Quake III, который описывал многопроходный рендеринг), и
другие. Peercy сотоварищи разработали технику для того, чтобы программы
с циклами и условиями выполнять на традиционных аппаратных архитектурах
при помощи нескольких проходов рендеринга. Шейдеры RenderMan разбивались
на несколько проходов, которые комбинировались во фреймбуфере. Позднее
появились языки, которые мы видим аппаратно ускоренными в DirectX и
OpenGL. Так шейдеры были адаптированы для графических приложений
реального времени.

Видеочипы раннего времени не были программируемы и исполняли только
заранее запрограммированные действия (fixed-function), например,
алгоритм освещения был жестко зафиксирован в железе, и нельзя было
ничего изменить. Затем, компании-производители видеочипов постепенно
ввели в свои чипы элементы программируемости, сначала это были очень
слабые возможности (NV10, известный как NVIDIA GeForce 256, уже был
способен на некоторые примитивные программы), которые не получили
программной поддержки в Microsoft DirectX API, но со временем
возможности постоянно расширялись. Следующий шаг был за и NV20 (GeForce
3) и NV2A (видеочип, примененный в игровой консоли Microsoft Xbox),
которые стали первыми чипами с аппаратной поддержкой шейдеров DirectX
API. Версия Shader Model 1.0/1.1, появившаяся в DirectX 8, была сильно
ограничена, каждый шейдер (особенно это относится к пиксельным) мог быть
сравнительно малой длины и сочетать весьма ограниченный набор команд. В
дальнейшем, Shader Model 1 (SM1 для краткости) была улучшена с
пиксельными шейдерами версии 1.4 (ATI R200), которые предлагали большую
гибкость, но также имели слишком ограниченные возможности. Шейдеры того
времени писались на так называемом assembly shader language, который
близок к ассемблеру для универсальных процессоров. Его низкий уровень
доставляет определенные сложности для понимания кода и программирования,
особенно, когда код программы большой, ведь он далек от элегантности и
структурированности современных языков программирования.

Версия Shader Model 2.0 (SM2), появившись в DirectX 9 (что было
поддержано видеочипом ATI R300, ставшим первым GPU с поддержкой
шейдерной модели версии 2.0), серьезно расширила возможности шейдеров
реального времени, предложив более длинные и сложные шейдеры и заметно
расширившийся набор команд. Была добавлена возможность расчетов с
плавающей запятой в пиксельных шейдерах, что также стало важнейшим
улучшением. DirectX 9, в лице возможностей SM2, также привнес и язык
шейдеров высокого уровня - high-level shader language (HLSL), весьма
похожий на язык Си. И эффективный компилятор, переводящий HLSL программы
в низкоуровневый код, "понятный" для аппаратных средств. Причем,
доступно несколько профилей, предназначенных для разных аппаратных
архитектур. Теперь, разработчик может писать один код HLSL шейдера и
компилировать его при помощи DirectX в оптимальную программу, для
установленного у пользователя видеочипа. После этого выходили чипы от
NVIDIA, NV30 и NV40, которые улучшили возможности аппаратных шейдеров
еще на шаг, добавив еще более длинные шейдеры, возможности динамических
переходов в вершинных и пиксельных шейдерах, возможность выборки текстур
из вершинных шейдеров и др.

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

***

Vertex Shader (Вершинный Шейдер)

Вершинные шейдеры - это программы, выполняемые видеочипами, которые
производят математические операции с вершинами (vertex, из них состоят
3D объекты в играх), иначе говоря, они предоставляют возможность
выполнять программируемые алгоритмы по изменению параметров вершин и их
освещению (T&L - Transform & Lighting). Каждая вершина определяется
несколькими переменными, например, положение вершины в 3D пространстве
определяется координатами: x, y и z. Вершины также могут быть описаны
характеристиками цвета, текстурными координатами и т.п. Вершинные
шейдеры, в зависимости от алгоритмов, изменяют эти данные в процессе
своей работы, например, вычисляя и записывая новые координаты и/или
цвет. То есть, входные данные вершинного шейдера - данные об одной
вершине геометрической модели, которая в данный момент обрабатывается.
Обычно это координаты в пространстве, нормаль, компоненты цвета и
текстурные координаты. Результирующие данные выполняемой программы
служат входными для дальнейшей части конвейера, растеризатор делает
линейную интерполяцию входных данных для поверхности треугольника и для
каждого пикселя исполняет соответствующий пиксельный шейдер. Очень
простой и грубый (но наглядный, надеюсь) пример: вершинный шейдер
позволяет взять 3D объект сферы и вершинным шейдером сделать из него
зеленый куб :).

До появления видеочипа NV20 у разработчиков было два пути, либо
использовать собственные программы и алгоритмы, изменяющие параметры
вершин, но тогда все расчеты делал бы CPU (software T&L), либо
полагаться на фиксированные алгоритмы в видеочипах, с поддержкой
аппаратной трансформации и освещения (hardware T&L). Первая же шейдерная
модель DirectX означала большой шаг вперед от фиксированных функций по
трансформации и освещению вершин к полностью программируемым алгоритмам.
Стало возможным, например, выполнять алгоритм скининга полностью на
видеочипах, а до этого единственной возможностью было их исполнение на
универсальных центральных процессорах. Теперь, с сильно улучшенными со
времен упомянутого чипа NVIDIA возможностями, с вершинами при помощи
вершинных шейдеров можно делать уже очень многое (кроме их создания,
разве что)...

***

Примеры того, как и где применяются вершинные шейдеры:

Скининг (skinning). Matrix pallete skinning для скелетной анимации
персонажей с большим количеством "костей". Примеры вы видите практически
во всех играх. Но приведу один скриншот из Call of Duty 2, над вершинами
каждого из персонажей поработал алгоритм скининга. Причем, с шейдерами
версии 3.0 сделать скининг стало заметно проще, для шейдеров версии 1.1
нужно было писать несколько шейдеров для каждого вида скининга (с
определенным количеством "костей").

Деформация объектов. Как самый явный и эффектный пример - создание
реалистичных волн в динамике. Примеры подобных решений наблюдаются в
играх F.E.A.R. и Pacific Fighters, причем в последнем сделана, пожалуй,
самая реалистичная вода реального времени, применяются вершинные шейдеры
3.0 и доступ к текстурам из них, настоящий Displacement Mapping в
дополнение к Bump Mapping:


Конечно, похожий эффект волн в динамике, как в F.E.A.R., может быть
запрограммирован и на пиксельном уровне (Morrowind), но в данном случае
речь об изменении реальной геометрии, что всегда реалистичнее выглядит.
Анимация объектов. Например, травы и деревьев в одном из первых
применений - 3DMark 2001 SE, алгоритм анимации был значительно улучшен в
следующем 3DMark 03:

Toon shading/Cel shading. Используется в некоторых играх для создания
специального эффекта "мультяшного" изображения:

Имитация ткани (Cloth Simulation) - для имитации поведения подобных
ткани материалов, которой очень не хватает в большинстве игр.

Сектора Лирики