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


Использование шейдеров в 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.

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

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

sampler Environment;
sampler SparkleNoise;
float4 k_s;

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

register(RegisterName)

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

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

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

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

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

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

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