Поделиться через


Использование шейдеров в Direct3D 9

Компиляция шейдера для конкретного оборудования

Шейдеры были впервые добавлены в Microsoft DirectX в DirectX 8.0. В то время были определены несколько виртуальных шейдеров, каждый примерно соответствующий конкретному графическому процессору, созданному лучшими поставщиками трехмерной графики. Для каждого из этих виртуальных шейдеров был разработан язык сборки. Программы, написанные в модели шейдера (имена vs_1_1 и ps_1_1 - ps_1_4) были относительно короткими и обычно написаны разработчиками непосредственно на соответствующем языке сборки. Приложение передает этот код языка сборки, доступный для чтения, в библиотеку D3DX с помощью D3DXAssembleShader и возвращает двоичное представление шейдера, которое, в свою очередь, передается с помощью CreateVertexShader или CreatePixelShader. Дополнительные сведения см. в пакете средств разработки программного обеспечения (SDK).

Ситуация в Direct3D 9 аналогична. Приложение передает шейдер HLSL в D3DX с помощью D3DXCompileShader и возвращает двоичное представление скомпилированного шейдера, которое, в свою очередь, передается в Microsoft Direct3D с помощью CreatePixelShader или CreateVertexShader. Среда выполнения ничего не знает о HLSL, она работает только с моделями шейдера на двоичной сборке. Это удобно, так как это означает, что компилятор HLSL может быть обновлен независимо от среды выполнения Direct3D. Вы также можете скомпилировать шейдеры в автономном режиме с помощью fxc.

Помимо разработки компилятора HLSL, Direct3D 9 также представила модели шейдеров на уровне сборки для предоставления функциональных возможностей последнего поколения графического оборудования. Разработчики приложений могут работать в сборке для этих новых моделей (vs_2_0, vs_3_0, ps_2_0, ps_3_0), но мы ожидаем, что большинство разработчиков переходят в HLSL для разработки шейдеров.

Конечно, возможность написания программы HLSL для выражения определенного алгоритма заливки не позволяет автоматически запускать его на любом оборудовании. Приложение вызывает D3DX для компиляции шейдера в двоичный код сборки с D3DXCompileShader. Одним из ограничений этой точки входа является параметр, определяющий, какой из моделей уровня сборки (или целевых объектов компиляции) компилятор HLSL должен использовать для выражения окончательного кода шейдера. Если приложение выполняет компиляцию шейдера HLSL во время выполнения (в отличие от времени компиляции или в автономном режиме), приложение может проверить возможности устройства Direct3D и выбрать целевой объект компиляции для сопоставления. Если алгоритм, выраженный в шейдере HLSL, слишком сложный для выполнения в выбранном целевом объекте компиляции, компиляция завершится ошибкой. Это означает, что в то время как HLSL является огромным преимуществом для разработки шейдеров, он не освобождает разработчиков от реалий доставки игр в целевую аудиторию с графическими устройствами различных возможностей. Как разработчик игр вы по-прежнему должны управлять многоуровневым подходом к визуальным элементам, что означает писать более совершенные шейдеры для более мощных графических карт и создавать более базовые версии для старых карт. Однако с хорошо написанным HLSL это бремя может быть значительно упрощено.

Вместо компиляции шейдеров HLSL с помощью D3DX на компьютере клиента во время загрузки приложения или при первом использовании многие разработчики предпочитают компилировать шейдеры из HLSL в двоичный код сборки, прежде чем они даже отправят. Это позволяет скрыть их исходный код HLSL от любопытных глаз, а также гарантирует, что все шейдеры, которые когда-либо будет запускать их приложение, прошли через их собственный процесс внутреннего обеспечения качества. Удобная программа для компиляции шейдеров в автономном режиме — fxc. Это средство имеет ряд параметров, которые можно использовать для компиляции кода для указанного целевого объекта компиляции. Изучение дизассемблированных выходных данных может быть очень образовательным во время разработки, если вы хотите оптимизировать шейдеры или как правило узнать возможности виртуальной машины шейдера на более подробном уровне. Ниже приведены основные варианты.

Инициализация констант шейдера

Константы шейдера содержатся в таблице констант. К этому можно получить доступ с помощью интерфейса ID3DXConstantTable. Глобальные переменные шейдера можно инициализировать в коде шейдера. Они инициализированы во время выполнения путем вызова SetDefaults.

Привязка параметра шейдера к определенному регистру

Компилятор автоматически назначает регистры глобальным переменным. Компилятор назначит Environment регистру sampler s0, SparkleNoise — регистру sampler s1, а k_s — константному регистру c0 (при условии, что никакие другие регистры выборки или константы ещё не были назначены) для следующих трех глобальных переменных:

sampler Environment;
sampler SparkleNoise;
float4 k_s;

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

register(RegisterName)

где RegisterName — это имя определенного регистра. В следующих примерах демонстрируется определенный синтаксис назначения регистра, в котором среда sampler будет привязана к регистру sampler s1, SparkleNoise будет привязана к регистру sampler s0, и k_s будет привязана к постоянному регистру c12:

sampler Environment : register(s1);
sampler SparkleNoise : register(s0);
float4 k_s : register(c12);

Отрисовка программируемого шейдера

Шейдер отрисовывается путем задания текущего шейдера на устройстве, инициализации констант шейдера, указывая устройству, откуда приходят различные входные данные, и, наконец, отрисовка примитивов. Каждое из них можно выполнить, вызвав следующие методы соответственно:

Отладка шейдеров

Расширение DirectX для Microsoft Visual Studio .NET предоставляет полностью интегрированный отладчик HLSL в интегрированной среде разработки Visual Studio .NET (IDE). Чтобы подготовиться к отладке шейдера, необходимо установить необходимые средства на компьютере (см. отладки шейдеров в Visual Studio (Direct3D 9)).

Руководство по программированию для HLSL