Введение в программирование трехмерных игр с DX9

       

Окно приложения 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; }


Содержание раздела