Файлы эффектов
В состав библиотеки Direct3D входит набор средств, которые предоставляют некий оберточный механизм для работы с вершинными и пиксельными шейдерами, установкой текстурных состояний и константами. Данная возможность реализуется с помощью интерфейса ID3DXEffect. Данный "оберточный" интерфейс инкапсулирует в себе следующие особенности:
- Содержат глобальные переменные, которые можно устанавливать из приложения;
- Позволяют манипулировать (управлять) состоянием механизма воспроизведения;
- Управляют текстурными состояниями и состояниями семплеров (определяют файлы текстур, инициализируют текстурные уровни и их настройки);
- Управляют механизмом визуализации с помощью шейдеров;
Рассмотрим пример использования файлов эффектов, написанных на языке HLSL. Ниже представлен простейший пример файла эффектов.
float4x4 WorldViewProj; float4x4 World; float4 Light;
texture Tex0 < string name = "texture.bmp"; >;
struct VS_INPUT { float4 position : POSITION; float3 normal : NORMAL; float2 texcoord : TEXCOORD0; };
struct VS_OUTPUT { float4 position : POSITION; float4 color : COLOR0; float2 texcoord : TEXCOORD0; };
VS_OUTPUT main_vs( VS_INPUT In ) { VS_OUTPUT Out; Out.position = mul( In.position, WorldViewProj ); float3 pos = mul( In.position, World ); float3 light = normalize(vecLight-pos); float3 normal = normalize(mul( In.normal, World )); float4 green = {0.0f, 1.0f, 0.0f, 1.0f}; Out.texcoord = In.texcoord; Out.color = green*dot(light, normal); return Out; }
sampler Sampler = sampler_state { Texture = (Tex0); MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; };
struct PS_INPUT { float2 texcoord : TEXCOORD0; float4 color : COLOR0; };
float4 main_ps( PS_INPUT In ) : COLOR0 { return tex2D(Sampler, In.texcoord ) * In.color; }
technique tec0 { pass p0 { VertexShader = compile vs_1_1 main_vs(); PixelShader = compile ps_1_1 main_ps(); } }
Пример 6.2.
Как видно из представленного примера, файлы эффектов объединяют в себе вершинный, пиксельный шейдеры, а также различные настройки режима воспроизведения.
Кроме того, файлы эффектов позволяют объединить ряд вариантов воспроизведения в одном файле. Такая модульность открывает широкие возможности по использованию одной программы на различных аппаратных решениях (компьютерах с различными техническими возможностями). Каждый файл эффектов может содержать один и более разделов technique, которые как раз и предназначены для различных способов реализации алгоритма воспроизведения. Каждый раздел techniques может содержать внутри себя один и более разделов rendering pass, которые объединяют в себе состояния устройства вывода, текстурные уровни, шейдеры. Следует заметить, что файлы эффектов не ограничены в использовании только программируемых элементов графического конвейера (шейдеров). Они также могут использоваться и в фиксированном конвейере для управления состояниями устройства вывода, источниками света, материала ми и текстурами. Применение нескольких разделов rendering pass позволяют получить различные эффекты визуализации, например, двухпроходный алгоритм построения тени с использованием буфера трафарета. Ниже представлен шаблон файла эффектов, в котором присутствует два раздела technique, плюс к этому второй раздел содержит два подраздела rendering pass.
technique tec0 { pass p0 // первый и единственный раздел rendering pass { // состояние устройства вывода, шейдеры, семплеры } }
technique tec1 { pass p0 // первый rendering pass { // состояние устройства вывода, шейдеры, семплеры }
pass p1 // второй раздел rendering pass { // состояние устройства вывода, шейдеры, семплеры } }
Для управления файлами эффектов из приложения необходимо воспользоваться методами интерфейса ID3DXEffect. Вначале необходимо объявить переменную интерфейсного типа ID3DXEffect, и возможно переменную для буфера ошибок.
C++ | LPD3DXEFFECT Effect = NULL; LPD3DXBUFFER BufferErrors = NULL; |
Pascal | var Effect: ID3DXEffect; BufferErrors: ID3DXBuffer; |
- Ссылка на устройство вывода;
- Имя файла эффекта;
- Набор макро определений (может быть пустым);
- Указатель на интерфейс ID3DXInclude для обработки включений в файле эффекта (может быть пустым);
- Набор флагов компиляции (может быть нулем);
- Указатель на интерфейс ID3DXEffectPool для обработки общих параметров в эффекте (может быть пустым);
- Указатель на полученный результат;
- Указатель на буфер ошибок.
C++ | D3DXCreateEffectFromFile( device, "effect.fx", NULL, NULL, 0, NULL, &Effect, &BufferErrors) |
Pascal | D3DXCreateEffectFromFile(device, ' effect.fx ', nil, nil, 0, nil, Effect, BufferErrors); |
C++ | Effect->SetTechnique("tec0"); |
Pascal | Effect.SetTechnique('tec0'); |
C++ | unsigned int numPasses = 0; Effect->Begin(&numPasses, 0); for(unsigned int pass = 0; pass < numPasses; pass++) { Effect->BeginPass(pass); device->DrawPrimitive(...); Effect->EndPass(); } Effect->End(); |
Pascal | var numPasses: DWord; pass: DWord; ... Effect._Begin(@numPasses, 0); for pass:=0 to numPasses-1 do begin Effect.BeginPass(pass); Device.DrawPrimitive(...); Effect.EndPass; end; Effect._End; |
SetBool() SetInt() SetMatrix() SetString() SetTexture() SetVector()
Следует отметить еще одно достоинство файлов эффектов. Для работы с ними существует программа EffectEdit, которая поставляет вместе с DirectX SDK. Эта программа позволяет загружать файлы эффектов и осуществлять рендеринг сцены при установленных настройках графического конвейера (шейдеров, текстур, состоянийустройства воспроизведения и др.). Кроме того, утилита EffectEdit может быть использована в качестве отладочного механизма ваших шейдерных программ.