Графика DirectX в Delphi
Шрифт:
bmp.LoadFromFile ('Claudia.bmp'); // Загрузка растра
k := 0;
for i := 0 to 199 do
for j := 0 to 145 do begin
with VPoints [k] do begin
X := random (145);
Y := random (200);
Steps [i, j].StepX := (j - X) / 10;
Steps [i, j].StepY := (i - Y) / 10;
Z := 0.0;
// Цветовые веса пиксела растра
R := GetRValue (bmp.Canvas.Pixels [j, i]);
G := GetGValue (bmp.Canvas.Pixels [j, i]);
В := GetBValue (bmp.Canvas.Pixels [j, i]) ;
RHW := 0.0;
Color := D3DCOLOR__XRGB(R, G, B); // Цвет примитива
end;
Inc (k);
end;
bmp.Free ;
...
Приращения
var
Steps : Array [0..199, 0..145] of TStep;
procedure TfrmD3D.ApplicationEventslIdle(Sender: TObject;
var Done: Boolean);
var
hRet : HRESULT;
i, j : Integer;
begin
if FActive then begin
Inc (Frames);
hRet := Render;
if FAILED(hRet) then begin
FActive := False;
ErrorOut ('Render', hRet);
Exit;
end;
ThisTickCount := GetTickCount;
if ThisTickCount - LastTickCount > 25 then begin Caption := Format('%6.2f ,
[frames * 1000 / (ThisTickCount - LastTickCount)]);
Frames := 0; Inc (Count);
// Цикл движения точек в 20 кадров
if Count <= 20 then MovePoints else begin
for i := 0 to 199 do
for j := 0 to 145 do begin
Steps [i, jJ.StepX := -Steps [i, j].StepX;
Steps [i, jJ.StepY := -Steps [i, jj.StepY;
end;
Count := 0;
end;
end;
LastTickCount := GetTickCount;
end;
Done := False;
end;
Обратите внимание, что клиентская область окна в этих двух примерах неквадратная, размеры его подогнаны для конкретных образов примеров.
Итак, мы научились из отдельных точек формировать весьма сложные образы, но такой подход годится только для простых, или тестовых примеров и небольших изображений. На количество используемых примитивов системой наложено ограничение, и работа с десятками тысяч примитивов, как мы видим из этого примера, приводит к существенному снижению FPS.
Отрезки
Для рисования отрезков в Direct3D предусмотрены два типа примитивов: независимые отрезки и связанные отрезки. Начнем постижение этой темы с первого из этой пары типа примитивов.
Для построения независимых отрезков первым аргументом метода DrawPrimitive указывается константа D3DРТ_LINELISТ. По считываемым попарно из потока вершинам строятся отдельные, несвязанные, отрезки прямой.
Несложный пример из каталога Ех1б является иллюстрацией на эту тему. На экране строятся два отрезка красного цвета, параллельные
Обратите внимание, что собственно при построении примитивов последним аргументом передается не количество вершин, а количество примитивов:
hRet := FD3DDevice. DrawPrimitive (D3DPT_LINELIST, 0, 2) ;
Если данных, поступающих из потока, недостаточно, ошибка генерироваться не станет, поскольку все недостающие данные будут считаться нулевыми.
Константа D3DРТ_LINELISТ является признаком другого примитива - группы связанных отрезков. В этом случае вершины, считываемые из потока, задают характеристики вершин, последовательно соединяемых отрезками прямой.
В проекте каталога Ех17 создается пятиугольник (рис. 7.9), в построении которого используется пять связанных отрезков.
Для получения пятиугольника требуется шесть точек, координаты первой и последней из них совпадают. Чтобы оживить картинку, текущие координаты вершин опираются на увеличивающееся значение переменной Angle:
for i := 0 to 5 do
with VPoints [i] do begin
X := 150 + cos (Angle +1*2* Pi /5) * Radius;
Y := 150 + sin (Angle +i*2*Pi/5) * Radius;
end;
Обращаю внимание на параметры метода воспроизведения примитивов:
hRet := FD3DDevice.DrawPrimitive(D3DPT_LINESTRIP, 0, 5);
Надеюсь, остальной код вопросов у вас не вызывает.
Теперь нам стоит обсудить, как воспроизводить одновременно несколько независимых групп примитивов. Организовать такое воспроизведение можно разными способами: хранить вершины в одном буфере, либо использовать отдельные буферы для каждой группы вершин.
Разберем первый вариант на примере проекта каталога Ех18. На экране вращаются два многоугольника: пятиугольник и квадрат (рис. 7.10).
Массив vpoints хранит координаты 11 вершин: первые 6 связаны с пятиугольником, оставшиеся предназначены для построения квадрата.
Квадрат и Пентагон вращаются в противоположные стороны с различными скоростями:
for i := 0 to 5 do // Первыми хранятся координаты вершин Пентагона