Суровая правда жизни о Direct3D
Спецвыпуск Хакер, номер #004, стр. 004-098-4
Листинг №3 - Main.cpp, начало инициализации.
HRESULT InitializeD3D()
{
HRESULT hr; //Данные о результате выполнения процедуры
hr = DirectDrawCreateEx(NULL, (VOID**)&lpDD, IID_IDirectDraw7, NULL); //Создадим интерфейс DirectDraw'а
if(FAILED(hr)) //Проверим на ошибки
return hr;
hr = lpDD->QueryInterface(IID_IDirect3D7, (VOID**)&lpD3D); //Создадим интерфейс Direct3D
if(FAILED(hr))
return hr;
Конец листинга 3.
Теперь надо поставить режим работы DirectDraw. Делается это с помощью метода SetCooperativeLevel интерфейса IDirectDraw7. Первый параметр - окно, то есть HWND, вот и запишем туда hWnd. Второй параметр - пресловутые особенности режима. Мы будем работать в полноэкранном режиме (флаг DDSCL_FULLSCREEN), раз так, значит у нас эксклюзивный режим (DDSCL_EXCLUSIVE), и если вдруг повиснет, будет работать Ctrl+Alt+Del :) (DDSCL_ALLOWREBOOT), и фактически вторым параметром будет являться DDSC_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT. Теперь пора уже и поменять разрешение экрана на 1280x1024x24, хотя нет, 24 - слишком жирно. Пусть будет 16. Давай-ка вызовем метод SetDisplayMode все того же интерфейса. Первые два параметра - разрешение (1280х1024). Третий - глубина цвета (16), четвертый - FPS (0 - пусть какое угодно будет, все равно это работает хреново), пятый - флаги (ничего дельного тут нет, ставим 0). Следующее место вызвало у меня в свое время массу недовольств, но когда я понял что к чему, было противно, что я сразу не догадался. Дабы уберечь тебя от моей ошибки, я тебе все тут покорно расскажу. Итак, мы приступаем к созданию серфайсов (IDirectDrawSurface7) - цепочки двойной буферизации. Сначала надо создать главную серфайсу. Делается это так (в общем, при создании практически любой серфайсы это делается так). Объявляем переменную типа DDSURFACEDESC2, например, ddsd2. Опустошаем ее ZeroMemory(&ddsd2, sizeof(DDSURFACEDESC2)) - &ddsd2 - указатель на ddsd2, sizeof - размер (параметр - тип (класс, структура и т.д.)). И давай заполнять параметры. Размер dwSize будет равен sizeof(ddsd2) (ddsd2.dwSize = sizeof(ddsd2)). Дальше - флаги. Так как нам нужны дополнительные параметры (в капсах), нужен флаг DDSD_CAPS, и так как у нас есть внеэкранные буферы, нужен флаг DDSD_BACKBUFFERCOUNT (ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;). Дальше - капсы. Нужен DDSCAPS_COMPLEX - серфайса не одна в цепочке буферизации, DDSCAPS_FLIP - разрешен метод Flip (метод копирования изображения из одной серфайсы в другую при буферизации в полноэкранном режиме). DDSCAPS_PRIMARYSURFACE - эта серфайса - главная. DDSCAPS_3DDEVICE - на ней рисует Direct3D девайс (ddsd2.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;). Дальше осталось добавить, что внеэкранный буфер у серфайсы 1 (ddsd2.dwBackBufferCount = 1;). Для того чтобы непосредственно создать серфайсу, надо воспользоваться методом CreateSurface все того же интерфейса IDirectDraw7. Первый его параметр - DDSURFACEDESC* (т.е. - указатель), так и пишем: &ddsd2. Второй параметр - указатель на создаваемую серфайсу, нацарапаем &lpM. Последний параметр значит то же, что и у DirectDrawCreateEx, NULL. Вот теперь мы создадим внеэкранный буфер. Для его создания нам понадобится лишь переменная типа DDSCAPS2, пусть будет ddscaps. В нее мы запишем DDSCAPS_BACKB.UFFER - эта серфайса - внеэкранный буфер. DDSCAPS_3DDEVICE - на него рисует Direct3D девайс. DDSCAPS_FLIP - разрешить метод Flip. Больше нам ничего дельного указывать в капсах не надо (DDSCAPS2 ddscaps = { DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE | DDSCAPS_FLIP, 0, 0, 0 };). Теперь мы ее создадим. Но сделаем это хитро - воспользовавшись методом GetAttachedSurface интерфейса IDirectDrawSurface7. Первый параметр - DDSCAPS2* - наш любимый &ddscaps. Второй - указатель на создаваемую серфайсу - &lpBB. Все, что мы сейчас натворили, можно увидеть в листинге: