Окно приложения 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.
ПРИМЕЧАНИЕ
Поскольку большая часть подготовительной работы, такая как установка освещения, материалов и текстур, выполняется в файле эффекта, в коде приложения достаточно создать эффект и разрешить его использование. В примере объявлены следующие глобальные переменные, относящиеся к рассматриваемой теме:
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; }