ЖУРНАЛ ХАКЕР

Суровая правда жизни о Direct3D

Спецвыпуск Хакер, номер #004, стр. 004-098-3


Листинг №1 - main.cpp, подключение заголовков.

#define D3D_OVERLOADS //Разрешаем использование специальных функций и перегруженных операторов, облегчающих работу с Direct3D

#include <windows.h> //Подключаем виндовский заголовок для работы с окнами и т.д.

#include <ddraw.h> //Подключаем заголовок DirectDraw'а, он нужен для Direct3D

#include <d3d.h> //Ну и самое главное - заголовок Direct3D

#include <tchar.h> //Заголовок, в котором определены такие функции, как _T и т.д.

#include <time.h> //В этом заголовке объявлены некоторые временные функции (например, для получения FPS)

Конец листинга 1.

Таким образом мы уже имеем 6 строк нашей проги (скажу тебе по секрету, их будет 219 :))! Далее надо объявить указатели на интерфейсы DirectX. Нам нужен один указатель IDirectDraw7, один - IDirect3D7, один - IDirect3DDevice7 (именно этот интерфейс и работает с 3D графикой), два - IDirectDrawSurface7 (этот интерфейс является "хранителем" аппаратно-зависимых изображений, а два их нужно для двойной буферизации, один - экранный буфер, другой - внеэкранный). Еще надо объявить переменные: массив на 6 элементов типа D3DVERTEX (эта структура описывает точку в 3D, 6 их нужно, т.к. 3 - точки полигона, два же по три - для "двухсторонности" - помнишь рендеринг по часовой и против часовой стрелки - кажется глупо и неудобно, хотя в большинстве случаев это совсем наоборот), одна - D3DMATERIAL7 (описание цвета, отражаемости и т.д.), одна - D3DLIGHT7 (описание источников света) и одна - HWND (описание окна).

Листинг №2 - main.cpp, объявление переменных.

LPDIRECTDRAW7 lpDD; //Интерфейс IDirectDraw7

LPDIRECT3D7 lpD3D; //IDirect3D7

LPDIRECT3DDEVICE7 lpD3DD; //IDirect3DDevice7

LPDIRECTDRAWSURFACE7 lpBB; //IDirectDrawSurface7 - "задний" буфер

LPDIRECTDRAWSURFACE7 lpM; //IDirectDrawSurface7 - буфер экрана

D3DMATERIAL7 mat; //Так называемый материал - данные о цвете

D3DVERTEX vtx[6]; //Данные о вершинах

D3DLIGHT7 d3dLight; //"Лампа" - освещение

HWND hWnd; //Структура, описывающая окно

Конец листинга 2.

Гхм... Сейчас будет уже интереснее...

Пытка №3 - выковыривание мозгов.

Опять же, а зачем?!? Ответ очень похож на вопрос: а зачем ему мозги??!?

Отныне мы будем ее инициализировать. Всю инициализацию мы запихнем в огромную функцию типа HRESULT InitializeD3D(), она будет возвращать ошибки D3D, если они возникнут. Для начала мы создадим интерфейс IDirectDraw7. Вызовем функцию DirectDrawCreateEx (в старых версиях DX, до седьмой, вместо нее была DirectDrawCreate, но, благодаря большим изменениям в DX7, появилась вышеуказанная). Ее первый параметр - гид девайса, т.к. я не знаю, какой конкретно девайс стоит на твоей машине, пишем туда NULL - пусть определяет сам. Второй параметр - указатель, в который он запишет адрес созданного нами интерфейса, торжественно впишем туда (VOID**)&lpDD. Третий параметр является гидом IDirectDraw7, поэтому он ВСЕГДА должен быть IID_IDirectDraw7 (к чему такая тупость, я не понимаю). Последний, четвертый параметр зарезервирован и предназначен для каких-то будущих возможностей COM, а пока не используется и глючит, если его значение не NULL. Далее надо создать интерфейс IDirect3D7. Благодаря свирепым проискам COM, это сделать очень просто - его надо создать из IDirectDraw7, воспользовавшись методом QueryInterface, первым параметром которого является гид создаваемого интерфейса (в данном случае - IID_IDirect3D7), а вторым - указатель ((VOID**)&lpD3D). Но это еще не все, надо проверять этот отстой на ошибки (поэтому у нас функция типа HRESULT - мы будем все эти ошибки возвращать). Для этого создадим сразу после объявления функции переменную hr типа HRESULT и ей будем присваивать значение вызываемого метода. А после будем проверять таким вот образом: if(FAILED(hr)) return hr;. Итак, а теперь листинг начала инициализации:

Назад на стр. 004-098-2  Содержание  Вперед на стр. 004-098-4