Краснов Михаил
Шрифт:
Окрасив задний буфер чистым синим цветом, нам остается только переставить буферы - вызываем метод Present объекта устройства. Если третий аргумент метода нулевой, то идентификатором окна, в котором происходит работа, берется значение, установленное ранее, во время инициализации работы системы. Все остальные параметры метода или не используются, или при указанных нулевых значениях задают работу со всей клиентской областью окна, что, как правило, и необходимо.
В состоянии ожидания сообщений беспрерывно вызывается функция Render, если окно приложения не минимизировано:
procedure TfrmDBD.ApplicationEventslMinimize(Sender: TObject);
begin
FActive := False; // При минимизации окна приложения флаг опускаем
end;
procedure TfrmDSD.ApplicationEventslRestore(Sender: TObject);
begin
FActive := True; // Окно восстановлено, флаг поднимаем
end;
Помимо непрерывной перерисовки окна периодически подсчитывается и выводится в его заголовке значение FPS:
procedure TfrmDSD.ApplicationEventslIdle(Sender: TObject;
var Done: Boolean);
var
hRet : HRESULT;
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 > 50 then begin
// Подсчет и вывод FPS
Caption := 'FPS = ' + Format('%6.2f',
[frames * 1000 / (ThisTickCount - LastTickCount)]);
Frames := 0;
LastTickCount := GetTickCount;
end;
end;
Done := False;
end;
Минимальное по сложности приложение, использующее DirectSD, мы разобрали, теперь попробуем проверить один момент. В проекте каталога Ех02 левая и правая половины окна окрашиваются в синий и красный цвета соответственно. Клиентская область окна имеет размер 300x300 пикселов. В функции Render для задания областей окрашивания используется переменная wrkRect типа TRect:
SetRect (wrkRect, 0, 0, 150, 300); // Левая область окна
hRet := FDSDDevice.Clear(1, @wrkRect, D3DCLEAR_TARGET,
D3DCOLOR__XRGB(0, 0, 255), 0.0, 0); // Первую область
// окрашиваем синим
if FAILED(hRet) then begin
Result := hRet;
Exit;
end;
SetRect (wrkRect, 150, 0, 300, 300); // Правая область
hRet := FDSDDevice.Clear(1, @wrkRect, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(255, 0, 0), 0.0, 0); // Вторую область
// окрашиваем красным
if FAILED(hRet) then begin
Result :=0 hRet;
Exit;
end;
Проект каталога Ех03 вы сможете разобрать и без моей помощи, это несложная модификация предыдущего примера, отличающаяся только тем, что значения цветовых весов со временем меняются. Я же обращу ваше внимание на одну немаловажную особенность последних двух примеров: при изменении размеров окна его половинки окрашиваются так, будто в коде отслеживаются его текущие размеры. Делаем важный вывод: размеры клиентской области окна на момент инициализации Direct3D определяют область вывода на весь сеанс работы с графической системой.
Тип TColor и цвет в DirectSD
Цвет в Direct3D задается 32-битным числом, так называемый формат ARGB. Последний байт этого числа задает вес синего цвета (В), предпоследний - JS зеленого (G), второй - красного (R). Смысл первого байта раскроем попозже, пока же его значение никак не влияет на результат работы программ.
К В первом примере для окрашивания окна в чистый синий строку очистки заднего буфера можно записать так:
hRet := FD3DDevi.ee.Clear(0, nil, D3DCLEARJTARGET, $000000FF, 0.0, 0);
В типе TColor, с которым вам приходилось часто работать в Delphi, также задействованы четыре байта, но последний байт отвечает за красный, а второй - за синий цвета. Потренируемся в переводе цвета из одного формата в другой и обратимся за помощью к проекту каталога Ех04.
На форме появилось два дополнительных объекта: кнопка Color и компонент, связанный с диалогом задания цвета. Переменная DXColor типа DWORD хранит текущее значение цвета, в который окрашивается задний буфер. При в нажатии кнопки появляется диалог указания цвета. Выбранный цвет устанавливается значением DXColor: