Расчет освещенности. Файлы эффектов
Файлы эффектов
В состав библиотеки 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; |
Для загрузки и компиляции файла эффектов предназначена функция D3DXCreateEffectFromFile(), которая имеет следующие параметры:
- Ссылка на устройство вывода;
- Имя файла эффекта;
- Набор макро определений (может быть пустым);
- Указатель на интерфейс ID3DXInclude для обработки включений в файле эффекта (может быть пустым);
- Набор флагов компиляции (может быть нулем);
- Указатель на интерфейс ID3DXEffectPool для обработки общих параметров в эффекте (может быть пустым);
- Указатель на полученный результат;
- Указатель на буфер ошибок.
C++ |
D3DXCreateEffectFromFile( device, "effect.fx", NULL, NULL, 0, NULL, &Effect, &BufferErrors) |
Pascal |
D3DXCreateEffectFromFile(device, ' effect.fx ', nil, nil, 0, nil, Effect, BufferErrors); |
Следующим шагом является установка активного раздела technique. Это реализуется с помощью вызова метода SetTechnique интерфейса ID3DXEffect, где в качестве параметра передается название раздела technique.
Затем необходимо определить количество рендер проходов (разделов rendering pass ), которые будут выполняться. Делается это при помощи вызова метода Begin интерфейса ID3DXEffect, который имеет два параметра: первый параметр – возвращаемое значение количества разделов pass и второй параметр – флаг, указывающий на необходимость сохранения состояния режимов воспроизведения (значение ноль). И заключительный шаг состоит в организации цикла по всех разделам rendering pass с активацией текущего на каждом шаге. На каждой итерации вызывается необходимый код вывода примитива.
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; |
Также как и в программах, написанных на языке HLSL, в файлы эффектов можно передавать параметры. Установка значений параметров осуществляется через вызов методов SetXXX интерфейса ID3DXEffect. Ниже представлены основные методы передачи параметров в файл эффектов:
SetBool() SetInt() SetMatrix() SetString() SetTexture() SetVector()
Следует отметить еще одно достоинство файлов эффектов. Для работы с ними существует программа EffectEdit, которая поставляет вместе с DirectX SDK. Эта программа позволяет загружать файлы эффектов и осуществлять рендеринг сцены при установленных настройках графического конвейера (шейдеров, текстур, состояний устройства воспроизведения и др.). Кроме того, утилита EffectEdit может быть использована в качестве отладочного механизма ваших шейдерных программ.