Итак, приступаем к изучению части DirectX, связанной с трехмерной графикой, хотя наши первые построения будут выполняться на плоскости. Теперь большая часть изученного в предыдущих главах книги непосредственно нами использоваться не будет, но многие подходы, понятия и приемы, с которыми мы уже познакомились, перекликаются с новым материалом. Например, в наших проектах мы встретим знакомые понятия главного объекта и порождаемых его методами вспомогательных объектов, и последовательность выполняемых нами действий будет во многом родственна предыдущим примерам.
Начнем наш путь с простейшего примера, проекта каталога Ex01. Если DirectDraw было удобнее начинать изучать с полноэкранных приложений, то с Direct3D мы познакомимся на примерах оконных приложений. В первом проекте данной главы клиентская часть окна окрашивается синим цветом. Это минимальное приложение, использующее Direct3D. Окно непрерывно перерисовывается, а в его заголовке выводится значение FPS.
Вначале бегло посмотрим код, потом некоторые ключевые моменты обсудим подробнее.
Прежде всего, замечаем, что в списке uses модуля дописан модуль DirectXGraphics. Это базовый модуль, играющий для наших последующих примеров такую же роль, какую играл ранее модуль DirectDraw. В этом модуле содержится описание базовых интерфейсов, типов и констант.
Имя формы этого и последующих примеров я задал frmD3D.
В разделе private описания класса формы мною внесены следующие строки: FD3D IDIRECT3D8; // Главный объект
FD3DDevice IDIRECT3DDEVICE8; // Объект устройства
FActive BOOL; // Вспомогательный флаг
ThisTickCount DWORD; // Отсчет времени для подсчета FPS
LastTickCount DWORD;
function InitDSD : HRESULT; // Инициализация системы
function Render HRESULT; // Воспроизведение
procedure Cleanup; // Удаление объектов
procedure ErrorOut (const Caption : PChar; const hError : HRESULT);
Сообщение об ошибке выводится пока в отдельном окне, для оконных приложений здесь не должно возникать проблем:
procedure TfrmDSD.ErrorOut (const Caption : PChar;
const hError : HRESULT);
begin
FActive := False; // Остановить перерисовку окна
Cleanup; // Удалить все объекты
MessageBox (Handle, PChar(DXGErrorString (hError)), Caption, 0)
end;
Функция DXGErrorString возвращает описание ошибки, код которой передается в качестве аргумента. Эта функция представлена в модуле Directxcraphics.
В процедуре очистки памяти объекты высвобождаются знакомым нам способом:
procedure TfrmD3D.Cleanup;
begin
if Assigned (FDSDDevice) then begin
FD3DDevice._Release;
FD3DDevice := nil;
end;
if Assigned (FD3D) then begin
FD3D._Release;
FD3D := nil;
end;
end;
Данная процедура вызывается при выводе описания аварийной ситуации и при завершении работы приложения, в обработчике onDestroy окна.
Инициализация графической системы включает действия, смысл которых нам интуитивно понятен и без дополнительных комментариев:
Function TfrmD3D.InitD3D : HRESULT;
var
d3ddm : TD3DDISPLAYMODE; // Вспомогательные структуры
d3dpp : TD3DPRESENT_PARAMETERS;
hRet : HRESULT;
begin
FD3D := nil;
FD3DDevice := nil;
// Создаем главный объект
FD3D := Direct3DCreate8(D3D_SDK_VERSION);
if FD3D = nil then begin
Result := _FAIL;
Exit;
end;
// Получаем установки рабочего стола
hRet := FDSD.GetAdapterDisplayMode(D3DADAPTERJ3EFAULT, d3ddm);
if FAILED(hRet) then begin
Result := hRet;
Exit;
end;
// Заполняем структуру, задающую параметры работы
ZeroMemory(@d3dpp, SizeOf(d3dpp)); // Обнуляем поля
with d3dpp do begin
Windowed := True; // Используется оконный режим
SwapEffect := D3DSWAPEFFECT_DISCARD; // Режим переключения буферов
BackBufferFormat := d3ddm.Format; // Формат заднего буфера
end;
// Создаем вспомогательный объект, объект устройства
Result := FD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Handle,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
d3dpp, FD3DDevice);
end;
Главным интерфейсом является СОМ-объект класса IDIRECTSDS, методы которого позволяют получить доступ к функциям библиотеки. Главный объект создается первым, а уничтожается последним. Создается он с помощью функции Direct3DCreate8, единственным аргументом которой является константа, сообщающая системе, какая версия DirectX SDK использовалась при компиляции приложения.
Методы главного объекта позволяют узнать текущие установки видеосистемы, и следующим действием нашей программы служит вызов метода GetAdapterDisplayMode. Как правило, обязательным это действие является только для оконных приложений, поскольку такие установки требуются для задания параметров заднего буфера.
У метода GetAdapterDispiayMode два аргумента:
* константа, задающая адаптер, для которого запрашиваются установки; указатель на вспомогательную переменную, в которую помещается результат, являющийся описанием характеристик устройства.
Предопределенным значением первого аргумента пока может использоваться только D3DADAPTER_DEFAULT, нулевая константа, соответствующая первичному устройству. Для описания характеристик служит переменная типа TD3DDISPLAYMODE, запись:
TD3DDisplayMode = packed record
Width : Cardinal; // Ширина рабочего стола
Height : Cardinal; // Высота рабочего стола