Графика DirectX в Delphi
Шрифт:
Формат данных вершины, помимо пространственных координат, содержит еще две, связанные с наложением текстуры:
type
TCUSTOMVERTEX = packed record
X, Y, Z : Single;
U, V : Single; // Новая пара координат в формате вершины
end;
const
D3DFVF_CUSTOMVERTEX = D3DFVF_XYZ or D3DFVF_TEX1; // Новая константа
Итак, для наложения текстуры на объект для каждой вершины должны указываться текстурные координаты. Сейчас мы используем двумерную текстуру. Она представляет
Константа DSDFVFJTEXI является указанием на то, что координаты текстуры задаются именно парой чисел, максимальным может быть девять координат.
При инициализации буфера вершин используем тот же прием, что и в предыдущем примере, т. е. обходимся без вспомогательного массива. Но инициализация буфера производится один раз, в самом начале работы приложения.
Квадрат располагаем в центре экрана:
function TfrmD3D.InitVB : HRESULT;
var
Vertices : ^TCustomVertex;
hRet : HRESULT;
begin
// Буфер вершин на четыре вершины квадрата
hRet := FD3DDevice.CreateVertexBuffer(4 * SizeOf(TCustomVerrex), 0,
D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, FD3DVB);
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// Устанавливаем поток
hRet := FD3DDevice.SetStreamSource(0, FD3DVB, SizeOf(TCustomVertex));
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// Задаем шейдер вершин
hRet := FD3DDevice.SetVertexShader(D3DFVF_CUSTOMVERTEX);
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// Заполняем буфер данными
hRet := FD3DVB.Lock(0, 4 * SizeOf(TCustomVertex), PByte(Vertices), 0),
if Failed(hRet) then begin
Result := hRet;
Exit;
end;
// Левый нижний угол квадрата
Vertices.X = -0.5; // Координата на листе
Vertices.Y = -0.5;
Vertices.Z = 0; // Левый нижний угол текстуры
Vertices.U = 0;
Vertices.V = 0;
Inc(Vertices); // Переходим к следующей вершине
Vertices.X = -0.5; // Левый верхний угол квадрата
Vertices.Y = 0.5;
Vertices.Z = 0;
Vertices.U = 0;
Vertices.V = 1;
Inc(Vertices);
Vertices.X = 0.5; // Правый нижний угол квадрата
Vertices.Y = -0.5;
Vertices.Z = 0;
Vertices.U = 1;
V ertices.V = 0;
I nc(Vertices) ;
Vertices.X =0.5; //
Vertices.Y = 0.5;
V ertices.Z = 0;
V ertices.U = 1;
V ertices.V = 1;
R esult := FD3DVB.Unlock;
end;
Текстура создается с помощью отдельной функции, единственным аргументом которой является имя файла-прототипа:
function TfrmD3D.InitTexture (const FileName : String) : HRESOLT;
var
hRet : HRESULT;
d3dlr : TD3DLOCKED_RECT; // Вспомогательная запись
dwDstPitch : DWORD; // Шаг поверхности текстуры
X, Y : DWORD;
Bmp : tBitmap;
R, G, В : Byte;
begin
Bmp := TBitmap.Create;
Bmp.LoadFromfile (FileName);
// Создание объекта текстуры
hRet := FD3DDevice.CreateTexture (Bmp.Width, Bmp.Height, 0, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, FD3Texture);
if FAILED(hRet) then begin
Result := hRet;
Exit;
end;
// Запираем поверхность текстуры FD3Texture.LockRect(0, d3dlr, nil, 0);
dwDstPitch := d3dlr.Pitch; // Запоминаем шаг поверхности
// Заполняем поверхность данными из растра
for Y := 0 to Bmp.Height - 1 do
for X := 0 to Bmp.Width - 1 do begin
R := GetRValue (Bmp.Canvas.Pixels [X, DWORD (Bmp.Height - 1) - Y]);
G := GetGValue (Bmp.Canvas.Pixels [X, DWORD (Bmp.Height - 1) - Y]);
В := GetBValue (Bmp.Canvas.Pixels [X, DWORD (Bmp.Height - 1) - Y]);
PDWORD (DWORD(d3dlr.pBits)+Y*dwDstPitch + X * 4)^:=
D3DCOLOR_XRGB(R,G, B);
end;
Bmp.Free;
// Отпираем поверхность текстуры
Result := FD3Texture.UnlockRect(0);
end;
Первые два аргумента метода CreateTexture объекта устройства - ширина и высота создаваемой текстуры. Каждое из этих чисел должно быть степенью двойки. Это очень важное правило, не пропустите его. Растр может быть любого размера, но поверхность текстуры произвольные размеры иметь не может. Если необходимо использовать растр, размеры которого не равны степени двойки, его следует масштабировать, используя те же приемы, которые мы рассмотрели в нескольких примерах на тему применения DirectDraw.
Следующие два параметра метода для нас не важны, а вот на пятый аргумент, формат пиксела, надо обратить внимание. Выбор формата поверхности текстуры оставлен за разработчиком, который сам должен решить, какое значение из предлагаемого набора для него наиболее всего подходит. Для текстур, представляющих собой обычные растры, самым удобным является 32-битный формат, в котором на каждый пиксел приходится четверка чисел. Константа, соответствующая такому формату - D3DFMT_А8R8G8В8. Конечно, можно использовать и другие форматы, например "5-6-5", но при манипуляции с пикселами поверхности необходимо учитывать сделанный выбор.