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

Текстурирование

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >

Мультитекстурирование

Библиотека Direct3D позволяет накладывать на один полигон не одну, а сразу несколько текстур. Наложение на грань нескольких текстур называется мультитекстурированием. На текущий момент поддерживается до 8 наложений (уровней) текстур на одну грань. Схему (принцип) мультитекстурирования можно описать следующим образом. Первый текстурный уровень (с индексом 0) принимает на вход два значения: цвет текселя и диффузный цвет вершины; производит с ними указанные операции и передает результат на следующий (нижний) уровень. Полученное на предыдущем уровне значение цвета используется в качестве одного из аргумента текущего уровня и т.д. Схематично данные шаги мультитекстурирования можно представить так:


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

SetTextureStageState(<уровень>, D3DTSS_TEXCOORDINDEX, <номер координат>);

Так, например, чтобы указать, что второй уровень будет использовать текстурные координаты первого текстурного уровня, достаточно воспользоваться следующим вызовом метода: SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 ). И затем нужно загрузить (установить) текстуры в соответствующие текстурные уровни.

SetTexture( 0, tex1 );
SetTexture( 1, tex2 );

Можно указать для каждого текстурного уровня свои собственные текстурные координаты. В этом случае должен корректно измениться формат вершины при описании и набор FVF флагов. Ниже приведен пример описания вершины и FVF флагов для мультитекстурирования с двумя уровнями (текстурами) и текстурными координатами.

C++
struct CUSTOMVERTEX
{
    FLOAT x,  y,  z, rhw;      // координаты вершины
    FLOAT u1, v1;         // текстурные координаты первого уровня
    FLOAT u2, v2;         // текстурные координаты второго уровня
};

#define MY_FVF (D3DFVF_XYZ | D3DFVF_TEX2)
Pascal
type
MyVertex = packed record
      x, y, z, rhw: Single; // координаты вершины
      u1,v1: Single; // текстурные координаты первого уровня
      u2,v2: Single; // текстурные координаты второго уровня
end;

const
MY_FVF = D3DFVF_XYZRHW or D3DFVF_TEX2;

Вообще, число во флаге D3DFVF_TEX как раз и показывает, сколько текстурных уровней планируется задействовать при мультитекстурировании (D3DFVF_TEX1 … D3DFVF_TEX8). Для хранения второй и последующих текстур необходимо объявить соответствующее количество нужных переменных, произвести загрузку текстур с помощью функции D3DXCreateTextureFromFile() и установить текстуры в соответствующие текстурные уровни вызовов метода SetTexture (<номер уровня>, <текстура>). Ниже приведен пример возможного использования двух текстур при мультитекстурировании.

C++
LPDIRECT3DTEXTURE9 tex, tex2;
…
D3DXCreateTextureFromFile( device, "texture.bmp", &tex );
D3DXCreateTextureFromFile( device, "texture2.bmp", &tex2 );
…
device->SetTexture ( 0, tex );
device->SetTexture ( 1, tex2 );
Pascal
var
   tex, tex2: IDirect3DTexture9;
…
D3DXCreateTextureFromFile( device, 'texture.bmp', tex );
D3DXCreateTextureFromFile( device, 'texture2.bmp', tex2 );
…
device.SetTexture( 0, tex );
device.SetTexture( 1, tex2 );

При такой каскадной схеме мультитекстурирования мы должны для каждого текстурного уровня задать два цветовых аргумента и операцию над ними с помощью вызова метода SetTextureStageState интерфейса IDirect3DDevice9:

SetTextureStageState( <номер уровня>, D3DTSS_COLORARG1, <значение> ), 
SetTextureStageState( <номер уровня>, D3DTSS_COLORARG2, <значение> ), 
SetTextureStageState( <номер уровня>, D3DTSS_COLOROP, <операция> ).

Помимо уже известных значений констант для цветовых аргументов в данном вызове может быть использована константа D3DTA_CURRENT, которая говорит, что в качестве значения будет браться цвет из предыдущего текстурного уровня.

Также мы можем указать требуемый тип фильтрации текстур для каждого в отдельности текстурного уровня, указав в качестве первого аргумента его номер и вызвав метод SetSamplerState интерфейса IDirect3DDevice9.

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

…
points[0].u1 = 0.0f;
points[0].v1 = 1.0f;
points[0].u2 = 0.0f;
points[0].v2 = 3.0f;
…
device->SetTexture( 0, tex );
device->SetTexture( 1, tex );
…

Ниже приведен пример мультитекстурирования с помощью одной текстуры и двух текстурных уровней.

device->SetTexture(0, tex);
device->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
device->SetTexture(1, tex);
device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
device->SetTextureStageState(1, D3DTSS_COLOROP, <operation>);

operation = D3DTOP_MODULATE4X


operation = D3DTOP_ADD

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >
Олег Корсак
Олег Корсак
Латвия, Рига
Ренат Файзуллин
Ренат Файзуллин
Россия, Казань