Войти
ПрограммированиеТерминыГрафика

HLSL (2 стр)

Использование

Для компиляции шейдера можно использовать утилиту 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.

Примеры использования:

// D3D9
pDevice->CreatePixelShader( pByteCode,  // байткод шейдера
          &pShader   // шейдер
        );

// D3D10  
pDevice->CreatePixelShader( pByteCode,    // байткод шейдера
          ByteCodeLength,  // размер массива с кодом
          &pShader    // шейдер
        );

Компиляция средствами D3DX

При работе с D3D9 возможно использование следующих функций:

    // компиляция шейдера, источник данных - буффер с файлом
    D3DXCompileShader(  
       LPCSTR               pSrcData,    // [вх] hlsl код шейдера
        UINT                 SrcDataLen,  // [вх] длина кода в символах
       CONST D3DXMACRO*     pDefines,    // [вх] массив макросов<sup>1</sup>
        LPD3DXINCLUDE        pInclude,    // [вх] хендлер для директивы #include<sup>2</sup>
        LPCSTR               pFunctionName,  // [вх] имя входной точки шейдера
        LPCSTR               pProfile,    // [вх] версия шейдеров, под которую производится компиляция
        DWORD                Flags,    // [вх] флаги компиляции
        LPD3DXBUFFER*        ppShader,    // [вых] байткод шейдера
        LPD3DXBUFFER*        ppErrorMsgs,  // [вых] буффер с сообщениями об ошибках
        LPD3DXCONSTANTTABLE* ppConstantTable  // [вых] таблица констант<sup>3</sup>
  );

    // компиляция шейдера, источник данных - текстовый файл
    D3DXCompileShaderFromFile(  
        LPCSTR               pSrcFile,       // [вх] путь к файлу, содержащему hlsl код шейдера
        CONST D3DXMACRO*     pDefines,       // [вх] массив макросов<sup>1</sup>
        LPD3DXINCLUDE        pInclude,       // [вх] хендлер для директивы #include<sup>2</sup>
        LPCSTR               pFunctionName,  // [вх] имя входной точки шейдера
        LPCSTR               pProfile,       // [вх] версия шейдеров, под которую производится компиляция
        DWORD                Flags,      // [вх] флаги компиляции
        LPD3DXBUFFER*        ppShader,      // [вых] байткод шейдера
        LPD3DXBUFFER*        ppErrorMsgs,    // [вых] буффер с сообщениями об ошибках
        LPD3DXCONSTANTTABLE* ppConstantTable  // [вых] таблица констант<sup>3</sup>
  );

    // компиляция шейдера, источник данных - ресурс
    D3DXCompileShaderFromResource(  
        HMODULE              hSrcModule,      // [вх] хэндл модуля, содержащего ресурс
        LPCSTR               pSrcResource,    // [вх] идентификатор ресурса, хранящего код шейдера
        CONST D3DXMACRO*     pDefines,        // [вх] массив макросов<sup>1</sup>
        LPD3DXINCLUDE        pInclude,        // [вх] хендлер для директивы #include<sup>2</sup>
        LPCSTR               pFunctionName,   // [вх] имя входной точки шейдера
        LPCSTR               pProfile,        // [вх] версия шейдеров, под которую производится компиляция
        DWORD                Flags,              // [вх] флаги компиляции
        LPD3DXBUFFER*        ppShader,          // [вых] байткод шейдера
        LPD3DXBUFFER*        ppErrorMsgs,      // [вых] буффер с сообщениями об ошибках
        LPD3DXCONSTANTTABLE* ppConstantTable  // [вых] таблица констант<sup>3</sup>
  );

    // Наиболее подходящую версию шейдеров можно получить с помощью функций
   
    D3DXGet[Pixel/Vertex]ShaderProfile( IDirect3DDevice9* pDevice );

Аналоги в D3DX10:

D3DX10CompileFromMemory(LPCSTR pSrcData, SIZE_T SrcDataLen, LPCSTR pFileName, CONST D3D10_SHADER_MACRO* pDefines, LPD3D10INCLUDE pInclude, 
    LPCSTR pFunctionName, LPCSTR pProfile, UINT Flags1, UINT Flags2, ID3DX10ThreadPump* pPump, ID3D10Blob** ppShader, ID3D10Blob** ppErrorMsgs, HRESULT* pHResult);

D3DX10CompileFromFile(LPCSTR pSrcFile,CONST D3D10_SHADER_MACRO* pDefines, LPD3D10INCLUDE pInclude,
        LPCSTR pFunctionName, LPCSTR pProfile, UINT Flags1, UINT Flags2, ID3DX10ThreadPump* pPump, ID3D10Blob** ppShader, ID3D10Blob** ppErrorMsgs, HRESULT* pHResult);

D3DX10CompileFromResource(HMODULE hSrcModule, LPCSTR pSrcResource, LPCSTR pSrcFileName, CONST D3D10_SHADER_MACRO* pDefines, 
    LPD3D10INCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, UINT Flags1, UINT Flags2, ID3DX10ThreadPump* pPump, ID3D10Blob** ppShader, ID3D10Blob** ppErrorMsgs, HRESULT* pHResult);

Описание параметров:

ПараметрЗначение
pSrcFileпуть к файлу с исходным кодом
hSrcModuleхэндл модуля с ресурсами
pSrcResourceимя ресурса в модуле
pSrcDataисходный код шейдера
SrcDataLenразмер исходного кода в байтах
pDefinesмассив значений макросов1
pIncludeхендлер для директивы #include2
pFunctionNameимя входной точки
pProfileверсия шейдеров, под которую производится компиляция
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 регистра.

Пример (D3D9):

// установим текущим наш шейдер
Device->SetPixelShader( pShader );

// передадим константы
Device->SetPixelShaderConstantF( 0, (float*)Vector, 1 );

Аналогично можно передавать и данные типа int и bool. Для этого используются аналогичные функции SetPixelShaderConstantI и SetPixelShaderConstantB соответственно. Для работы с вершинными шейдерами используются аналогичные функции: SetVertexShader, SetVertexShaderConstant[F/I/B].

Пример (D3D10):

// установим текущим наш шейдер
Device-PSSetShader( pShader );

// передадим константы
Device->PSSetConstantBuffers( 0, 1, &pCBuffer );

В D3D10 константы объединяются в группы, называемые буфферами констант (Constant buffers). Такой подход позволяет эффективнее организовать процесс передачи данных в шейдер. В примере выше предполагается что pCBuffer является инициализированным указателм на ID3D10Buffer. Константные буфферы создаются аналогично вершинным и индексным, при этом полю структуры D3D10_BUFFER_DESC::BindFlags следует задать значение D3D10_BIND_CONSTANT_BUFFER.


Расширения
В комплект библиотеки D3DX входит мощное средство, делающее интеграцию шейдеров в приложение более удобным - API для работы с файлами эффектов (Effect, fx). Типовой fx - файл помимо кода шейдеров содержит наборы настроек для управления графическим конвейером (Render States) - такие как параметры отсечения (Culling), смешивания (Blending) и прочие, а так же так называемые техники (techniques) - структуры, позволяющие организовывать многопроходные эффекты с указанием шейдеров и опций граф. конвейера, используемых в каждом проходе. Такая организация информации избавляет от необходимости установки каждого шейдера либо стейта вручную. Вместо этого все необходимые настройки устанавливаются автоматически при активации эффекта.

Ссылки
В статье использованы материалы из архива MSDN и D3D SDK:
- HLSL
- HLSL Semantics
- DirectX SDK

Учебники и примеры(Gamedev.ru): Программирование шейдеров на HLSL.
Учебники и справочники (MSDN): Programming Guide for HLSL, Reference for HLSL.
Множество примеров и руководств содержится в DirectX SDK.
Большая библиотека готовых шейдеров от NVIDIA - NVIDIA Shader Library

IDE для работы с HLSL:
- NVIDIA FX Composer.
- AMD Render Monkey.

Страницы: 1 2

#DirectX, #шейдеры

11 июня 2009 (Обновление: 16 фев. 2011)

Комментарии [4]