Опубликован: 08.07.2007 | Доступ: свободный | Студентов: 1429 / 183 | Оценка: 4.43 / 4.02 | Длительность: 13:47:00
Специальности: Программист
Лекция 9:

Расчет освещенности. Файлы эффектов

Файлы эффектов

В состав библиотеки 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.

C++ Effect->SetTechnique("tec0");
Pascal
Effect.SetTechnique('tec0');

Затем необходимо определить количество рендер проходов (разделов 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 может быть использована в качестве отладочного механизма ваших шейдерных программ.