Компиляция эффекта (Direct3D 10)

После создания эффекта первым шагом является компиляция кода для проверка для синтаксических проблем. Для этого вызывается один из API компиляции (например, D3DX10CompileEffectFromFile, D3DX10CompileEffectFromResource, D3DX10CompileEffectFromMemory). Эти API вызывают компилятор эффекта fxc.exe который является компилятором, используемым для компиляции кода HLSL. Именно поэтому синтаксис кода в эффекте очень похож на код HLSL (есть несколько исключений, которые будут обработаны позже). Кстати, компилятор эффектов или компилятор hlsl (fxc.exe) находится в пакете SDK в папке служебных программ, чтобы при желании можно было скомпилировать шейдеры (или эффекты) в автономном режиме. См. документацию по запуску компилятора из командной строки.

Ниже приведен пример компиляции файла эффекта (из примера BasicHLSL10).

WCHAR str[MAX_PATH];
DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"BasicHLSL10.fx" );

hr = D3DX10CompileEffectFromFile( str, NULL, NULL, "fx_4_0", 
    D3D10_SHADER_ENABLE_STRICTNESS, 0, pd3dDevice, NULL, NULL, 
    &l_pBlob_Effect, &l_pBlob_Errors, NULL );

Includes

Одним из параметров является интерфейс включения. Создайте один из них, если вы хотите включить настраиваемое поведение при чтении включаемого файла. Это настраиваемое поведение выполняется каждый раз при создании эффекта (использующего указатель включения) или при компиляции эффекта (использующего указатель включения). Чтобы реализовать настроенное поведение включения, наследуйте класс из интерфейса Include. Это предоставляет классу два метода: Open и Close. Реализуйте пользовательское поведение в методах Open и Close.

Макросы

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

if( bAnimate )
    vAnimatedPos += float4(vNormal, zero) *  
        (sin(g_fTime+5.5)+0.5)*5;
        
    Output.Diffuse.a = one;         

Ниже приведено объявление для двух макросов.

D3D_SHADER_MACRO Shader_Macros[3] = { "zero", "0", "one", "1.0f", NULL, NULL };

Макросы представляют собой массив макросов с завершением NULL; где каждый макрос определяется с помощью структуры D3D_SHADER_MACRO .

Наконец, измените вызов эффекта компиляции, чтобы принять указатель на макросы.

D3DX10CreateEffectFromFile( str, Shader_Macros, NULL, 
    D3D10_SHADER_ENABLE_STRICTNESS, 0, pd3dDevice, NULL, NULL, 
    &g_pEffect10, NULL );

Флаги шейдера HLSL

Флаги шейдера указывают ограничения шейдера для компилятора HLSL. Эти флаги влияют на код, созданный компилятором шейдера, в том числе:

  • Рекомендации по размеру: оптимизируйте код.
  • Рекомендации по отладке: включение отладочной информации, предотвращение управления потоком.
  • Рекомендации по оборудованию: целевой объект компиляции и возможность запуска шейдера на устаревшем оборудовании.

Как правило, эти флаги могут быть логически объединены при условии, что вы не указали две конфликтующие характеристики. Список флагов см. в разделе Константы эффектов (Direct3D 10).

Флаги FX

Эти флаги используются при создании эффекта для определения поведения компиляции или эффекта среды выполнения. Список флагов см. в разделе Константы эффектов (Direct3D 10).

Проверка ошибок

Если во время компиляции возникает ошибка, API возвращает интерфейс, содержащий ошибки, возвращенные компилятором эффекта. Этот интерфейс называется ID3D10Blob. Однако он недоступен для чтения напрямую, возвращая указатель на буфер, содержащий данные (который является строкой), можно увидеть любые ошибки компиляции.

В этом примере в эффект BasicHLSL.fx была введена ошибка путем копирования первого объявления переменной дважды.

//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
float4 g_MaterialAmbientColor;      // Material's ambient color

// Declare the same variable twice
float4 g_MaterialAmbientColor;      // Material's ambient color

Эта ошибка привела к тому, что компилятор вернул следующую ошибку, как показано на следующем снимке экрана окна watch в Microsoft Visual Studio.

Снимок экрана: окно watch Visual Studio

Так как ошибка возвращается в указателе LPVOID, приведите ее к строке символов в окне watch.

Ниже приведен код, используемый для возврата ошибки из неудачной компиляции.

// Read the D3DX effect file
WCHAR str[MAX_PATH];
ID3D10Blob* l_pBlob_Effect = NULL;
ID3D10Blob* l_pBlob_Errors = NULL;
hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"BasicHLSL10.fx" );
hr = D3DX10CompileEffectFromFile( str, NULL, NULL, 
    D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, 
    &l_pBlob_Effect, &l_pBlob_Errors );

LPVOID l_pError = NULL;
if( l_pBlob_Errors )
{
    l_pError = l_pBlob_Errors->GetBufferPointer();
    // then cast to a char* to see it in the locals window
}

Отрисовка эффекта (Direct3D 10)