netlib.narod.ru< Назад | Оглавление | Далее >

19.7. Пример приложения: освещение и текстурирование в файле эффектов

Для разминки давайте создадим файл эффекта, который выполняет освещение и текстурирование трехмерной модели. Пример в работе использует только функции фиксированного конвейера, показывая что каркас эффектов не ограничен эффектами, использующими шейдеры. На рис. 19.1 показано окно примера Lighting and Texturing.


Рис. 19.1. Окно приложения Lighting and Texturing

Рис. 19.1. Окно приложения Lighting and Texturing. Текстуры, материал и режимы освещения заданы в файле эффекта


Файл эффекта выглядит следующим образом:

//
// Файл:     light_tex.txt
// Описание: Файл эффекта, устанавливающий состояния устройства
//           для освещения и текстурирования трехмерной модели
//

//
// Глобальные переменные
//

matrix WorldMatrix;
matrix ViewMatrix;
matrix ProjMatrix;

texture Tex;

//
// Выборка
//

// Связываем текстуру Tex c соответствующим этапом текстурирования S0
// и задаем режимы выборки для этапа выборки S0
sampler S0 = sampler_state
{
     Texture   = (Tex);
     MinFilter = LINEAR;
     MagFilter = LINEAR;
     MipFilter = LINEAR;
};

//
// Эффект
//

technique LightAndTexture
{
     pass P0
     {
          //
          // Устанавливаем разные режимы визуализации
          //
          pixelshader      = null;   // Пиксельных шейдеров нет
          vertexshader     = null;   // Вершинных шейдеров нет
          fvf = XYZ | Normal | Tex1; // Настраиваемый формат вершин
          Lighting         = true;   // Разрешаем освещение
          NormalizeNormals = true;   // Нормализуем нормали
          SpecularEnable   = false;  // Отключаем отражаемый свет

          //
          // Установка состояний преобразования
          //
          WorldTransform[0]   = (WorldMatrix);
          ViewTransform       = (ViewMatrix);
          ProjectionTransform = (ProjMatrix);

          //
          // Инициализируем источник освещения с индексом 0.
          // Мы заполняем все компоненты light[0] потому что
          // в документации Direct3D рекомендуется заполнять все
          // компоненты для повышения производительности
          //
          LightType[0]         = Directional;
          LightAmbient[0]      = {0.2f, 0.2f, 0.2f, 1.0f};
          LightDiffuse[0]      = {1.0f, 1.0f, 1.0f, 1.0f};
          LightSpecular[0]     = {0.0f, 0.0f, 0.0f, 1.0f};
          LightDirection[0]    = {1.0f, -1.0f, 1.0f, 0.0f};
          LightPosition[0]     = {0.0f, 0.0f, 0.0f, 0.0f};
          LightFalloff[0]      = 0.0f;
          LightRange[0]        = 0.0f;
          LightTheta[0]        = 0.0f;
          LightPhi[0]          = 0.0f;
          LightAttenuation0[0] = 1.0f;
          LightAttenuation1[0] = 0.0f;
          LightAttenuation2[0] = 0.0f;

          // Разрешаем использовать этот источник света

          LightEnable[0] = true;

          //
          // Устанавливаем компоненты материала. Это аналогично
          // вызову IDirect3DDevice9::SetMaterial.
          //
          MaterialAmbient  = {1.0f, 1.0f, 1.0f, 1.0f};
          MaterialDiffuse  = {1.0f, 1.0f, 1.0f, 1.0f};
          MaterialEmissive = {0.0f, 0.0f, 0.0f, 0.0f};
          MaterialPower    = 1.0f;
          MaterialSpecular = {1.0f, 1.0f, 1.0f, 1.0f};

          //
          // Привязываем объект выборки S0 к
          // этапу выборки 0, который задается Sampler[0].
          //
          Sampler[0] = (S0);
     }
}

В этом файле эффекта мы сперва устанавливаем состояния устройства, как было описано в разделе 19.3. Например, непосредственно в файле эффекта мы устанавливаем источник света и материал. Кроме того, мы задаем матрицы преобразования, текстуру и режимы выборки. Эти состояния будут применены для любых объектов, которые визуализируются с использованием техники LightAndTexture в проходе визуализации P0.

ПРИМЕЧАНИЕ
Обратите внимание, что ссылаясь на переменные из файла эффекта мы заключаем их имена в скобки. Например, для ссылок на матрицы преобразований мы должны писать (WorldMatrix), (ViewMatrix) и (ProjMatrix). Отсутствие скобок недопустимо.

Поскольку большая часть подготовительной работы, такая как установка освещения, материалов и текстур, выполняется в файле эффекта, в коде приложения достаточно создать эффект и разрешить его использование. В примере объявлены следующие глобальные переменные, относящиеся к рассматриваемой теме:

ID3DXEffect* LightTexEffect = 0;

D3DXHANDLE WorldMatrixHandle = 0;
D3DXHANDLE ViewMatrixHandle = 0;
D3DXHANDLE ProjMatrixHandle = 0;
D3DXHANDLE TexHandle = 0;

D3DXHANDLE LightTexTechHandle = 0;

Здесь нет ничего интересного — только указатель на ID3DXEffect и несколько дескрипторов. LightTexTechHandle — это дескриптор техники, на что указывает строка «Tech» в его имени.

Функция Setup выполняет следующие три действия: создает эффект, получает дескрипторы параметров эффекта и дескриптор той техники, которую мы будем использовать, и инициализирует некоторые из параметров эффекта. Вот код тех фрагментов функции, которые относятся к рассматриваемой теме:

bool Setup()
{
     HRESULT hr = 0;

     //
     // ...[Пропущена загрузка X-файла]
     //

     //
     // Создание эффекта
     //

     ID3DXBuffer* errorBuffer = 0;
     hr = D3DXCreateEffectFromFile(
           Device,           // связанное устройство
           "light_tex.txt",  // имя файла эффекта
           0,                // нет определений препроцессора
           0,                // нет интерфейса ID3DXInclude
           D3DXSHADER_DEBUG, // флаги компиляции
           0,                // нет совместного использования параметров
           &LightTexEffect,  // возвращает указатель на интерфейс эффекта
           &errorBuffer);    // возвращает сообщения об ошибках

     // Выводим любые сообщения об ошибках
     if(errorBuffer)
     {
          ::MessageBox(0, (char*)errorBuffer->GetBufferPointer(), 0, 0);
          d3d::Release<ID3DXBuffer*>(errorBuffer);
     }

     if(FAILED(hr))
     {
          ::MessageBox(0, "D3DXCreateEffectFromFile() - FAILED", 0, 0);
          return false;
     }

     //
     // Сохраняем дескрипторы часто используемых параметров
     //

     WorldMatrixHandle = LightTexEffect->GetParameterByName(0,
                                                  "WorldMatrix");
     ViewMatrixHandle  = LightTexEffect->GetParameterByName(0,
                                                  "ViewMatrix");
     ProjMatrixHandle  = LightTexEffect->GetParameterByName(0,
                                                  "ProjMatrix");
     TexHandle         = LightTexEffect->GetParameterByName(0, "Tex");
     LightTexTechHandle =
           LightTexEffect->GetTechniqueByName("LightAndTexture");

     //
     // Устанавливаем параметры эффекта
     //

     // Матрицы
     D3DXMATRIX W, P;

     D3DXMatrixIdentity(&W);
     LightTexEffect->SetMatrix(WorldMatrixHandle, &W);

     D3DXMatrixPerspectiveFovLH(
          &P, D3DX_PI * 0.25f, // 45 градусов
          (float)Width / (float)Height,
           1.0f, 1000.0f);

     LightTexEffect->SetMatrix(ProjMatrixHandle, &P);

     // Текстура
     IDirect3DTexture9* tex = 0;
     D3DXCreateTextureFromFile(Device, "Terrain_3x_diffcol.jpg", &tex);

     LightTexEffect->SetTexture(TexHandle, tex);

     d3d::Release<IDirect3DTexture9*>(tex);

     return true;
}

Функция Display прямолинейна и выполняет действия, описанные в разделе 19.6:

bool Display(float timeDelta)
{
     if(Device)
     {
          //
          // ...[Пропущено обновление камеры]
          //

          // Устанавливаем обновленную матрицу вида
          LightTexEffect->SetMatrix(ViewMatrixHandle, &V);

          //
          // Активируем технику и выполняем визуализацию
          //

          Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
                        0xffffffff, 1.0f, 0);
          Device->BeginScene();

          // Устанавливаем используемую технику
          LightTexEffect->SetTechnique(LightTexTechHandle);

          UINT numPasses = 0;
          LightTexEffect->Begin(&numPasses, 0);

          for(int i = 0; i < numPasses; i++)
          {
               LightTexEffect->Pass(i);

               for(int j = 0; j < Mtrls.size(); j++)
               {
                    Mesh->DrawSubset(j);
               }
          }
          LightTexEffect->End();

          Device->EndScene();
          Device->Present(0, 0, 0, 0);
     }
     return true;
}

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz