Для компиляции шейдера можно использовать утилиту fxc или средства D3DX.
Компиляция средствами fxc
По умолчанию fxc находится в директории <путь к SDK>\Utilities\bin\x86\fxc.exe. Это вполне обычный компилятор, используется так:
fxc <опции> <путь к файлу с кодом>. Список некоторых опций (для более детальной информации запустите fxc без параметров):
Флаг
Значение
/T<profile>
профиль, например ps_1_4. Список поддерживаемых значений можно посмотреть запустив fxc без параметров
/E<name>
входная точка
/I<include>
дополнительные пути для поиска файлов (для директивы #include)
/Od
не использовать оптимизации
/O{0,1,2,3}
степнь оптимизации 0..3. по умолчанию 1
/Zi
сохранять отладочную информацию
/Zpr
хранить матрицы в нотации [строка][столбец]
/Zpc
хранить матрицы в нотации [столбец][строка]
/Gpp
использовать половинную точность (float будет заменен на half где возможно)
/Gfa
не использовать динамический контроль исполнения кода
/Gfp
использовать динамический контроль исполнения кода
/Fo<file>
сохранить скомпилированный объект в файл
/Fc<file>
сохранить листинг на ассемблере в файл
/Fx<file>
сохранить листинг на ассемблере и в hex в файл
/Fh<file>
сохранить заголовочный файл
/Fe<file>
вывести сообщения об ошибках и предупреждениях компилятора в отдельный файл
/Vn<name>
использовать <name> как имя переменной в заголовочном файле
/Cc
вывод листинга на ассемблере
/P<file>
только препроцессинг файла (используется отдельно)
/D<id>=<text>
установить макрос id со значением text
/LD
использовать d3dx9_31.dll
/nologo
не писать copyright информацию
Пример: fxc /T ps_2_0 /E main /O2 /Fo "c:\work\bin\ps.bin" "c:\work\pixel_shader.hlsl"
Для дальнейшей работы откомпилированный код шейдера нужно загрузить и воспользоваться методами IDirect3DDevice9::CreatePixelShader, IDirect3DDevice9::CreateVertexShader (D3D9) или ID3D10Device::CreatePixelShader, ID3D10Device::CreateVertexShader, ID3D10Device::CreateGeometryShader.
версия шейдеров, под которую производится компиляция
Flags1
комбинация значений D3D10_SHADER_xxx
Flags2
комбинация значений D3D10_EFFECT_xxx
ppShader
буффер, содержащий скомпилированный код шейдера
ppErrorMsgs
сообщения об ошибках
pHResult
указатель на объект типа HRESULT.
По этому адресу будет помещен результат выполнения функции
1 - необходимо передать массив структур вида
struct D3DXMACRO
{
LPCSTR Name; // имя
LPCSTR Definition; // значение
};
Важно, чтобы массив завершала структура со значениями установленными в 0.
2 - пользовательская реализация интерфейса ID3DXInclude. См. подробности в DirectX SDK.
3 - для управления константами можно использовать интерфейс ID3DXConstantTable, который предосталвяет возможность устанавливать константы шейдера указывая не регистр, а имя константы, например:
// предполагается что pTable является инициализированным указателем на ID3DXConstantTable// установка массива данных типа float
pTable->SetValue( pDevice, "SomeConstant1", (void*)FloatArray, sizeof(float)*ARRAYSIZE(FloatArray));
// установка массива данных типа float (вариант 2)
pTable->SetFloatArray( pDevice, "SomeConstant1", FloatArray, ARRAYSIZE(FloatArray));
// установка одной константы типа float
pTable->SetFloat( pDevice, "SomeConstant2", FloatArray[0]);
Аналогично методам SetFloat и SetFloatArray присутствуют методы для передачи данных типа int, bool, D3DXVECTOR4, D3DXMATRIX. Для матриц существует дополнительный метод SetMatrixPointerArray, позволяющий передавать массив указателей на матрицы. Так же удобными могут оказаться методы SetMatrixTranspose, SetMatrixTransposeArray, SetMatrixTransposePointerArray. При работе с нимим матрицы, передаваемые в шейдер автоматически транспонируются. За более полной документацией обратитесь к DirectX SDK или MSDN.
Можно не использовать интерфейс ID3DXConstantTable, а передавать данные вручную. В этом случае необходимо указывать регистр, в который следует поместить передаваемую информацию, а так же количество регистров, которое потребуется, чтобы ее разместить. Важно не забывать, что один регистр рассчитан на хранение одного четырехмерного вектора. Такми образом float4 занимает 1 регистр, float2 - всеравно один регистр, а матрица float4x4 - 4 регистра.
Аналогично можно передавать и данные типа int и bool. Для этого используются аналогичные функции SetPixelShaderConstantI и SetPixelShaderConstantB соответственно. Для работы с вершинными шейдерами используются аналогичные функции: SetVertexShader, SetVertexShaderConstant[F/I/B].
В D3D10 константы объединяются в группы, называемые буфферами констант (Constant buffers). Такой подход позволяет эффективнее организовать процесс передачи данных в шейдер. В примере выше предполагается что pCBuffer является инициализированным указателм на ID3D10Buffer. Константные буфферы создаются аналогично вершинным и индексным, при этом полю структуры D3D10_BUFFER_DESC::BindFlags следует задать значение D3D10_BIND_CONSTANT_BUFFER.
Расширения В комплект библиотеки D3DX входит мощное средство, делающее интеграцию шейдеров в приложение более удобным - API для работы с файлами эффектов (Effect, fx). Типовой fx - файл помимо кода шейдеров содержит наборы настроек для управления графическим конвейером (Render States) - такие как параметры отсечения (Culling), смешивания (Blending) и прочие, а так же так называемые техники (techniques) - структуры, позволяющие организовывать многопроходные эффекты с указанием шейдеров и опций граф. конвейера, используемых в каждом проходе. Такая организация информации избавляет от необходимости установки каждого шейдера либо стейта вручную. Вместо этого все необходимые настройки устанавливаются автоматически при активации эффекта.