Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

DirectGraphics - программирование графики [Простейшее приложение DirectX Graphics (C++)]


Простейшее приложение DirectX Graphics (C++)

В сегодняшнем выпуске мы напишем простейшее DirectX Graphics приложение. Вообще в каждом выпуске планируется давать материал сразу для двух языков: C++ и C#. Но так как этот выпуск получился слишком объемным, материал по C# выйдет в следующем выпуске.

Для работы вам понадобится Microsoft DirectX SDK (April 2006), в принципе можно использовать и более раннюю версию, но тогда могут появиться некоторые несоответствия. В качестве среды разработки я использую Microsoft Visual Studio .NET 2003 для C++ приложений и Microsoft Visual Studio .NET 2005 для приложений на C# (используется .NET Framework 2.0).

Создание контекста устройства

Для того, чтобы приложение могло воспользоваться возможностями DirectX Graphics, необходимо создать экземпляр интерфейса IDirect3DDevice9. Для этого сначала необходимо инициализировать Direct3D, с помощью функции Direct3DCreate9. Затем заполним структуру D3DPRESENT_PARAMETERS, которая содержит в себе сведения параметрах вывода графики, таких как разрешение экрана, использование буфера глубины и т.д. Для нашего примера достаточно указать, что приложение будет работать в оконном режиме и вывод на экран заднего буфера будет производиться в отладочном режиме.

Что такое задний буфер? Дело в том, что DirectX Graphics выводит изображение не на экран, а в теневую область видеопамяти. Это делается для того, чтобы пользователь не видел процесса прорисовки изображения. После того как прорисовка закончена, DirectX Graphics делает невидимое видимым и выводит содержимое заднего буфера на экран.

Теперь создаем экземпляр интерфейса IDirect3DDevice9 методом CreateDevice. В параметрах метода указываем, что необходимо использовать аппаратное ускорение видеокарты [D3DDEVTYPE_HAL], обработку вершин осуществлять процессором [D3DCREATE_SOFTWARE_VERTEXPROCESSING]. Еще в функцию передается номер видеокарты, через которую будет выводиться изображение (по умолчанию 0), дескриптор окна [hWnd] и указатель на структуру D3DPRESENT_PARAMETERS [&present]. Последним передается указатель на указатель IDirect3DDevice9 (извините за каламбур, но так и есть), который является выходным параметром [&device].

void CreateDirect3D()
{
    d3d = Direct3DCreate9(D3D_SDK_VERSION);

    D3DPRESENT_PARAMETERS present;
    ZeroMemory(&present, sizeof(present));
    present.Windowed = true;
    present.SwapEffect = D3DSWAPEFFECT_DISCARD;

    d3d->CreateDevice(0, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &device);
}

Вывод графики на экран

Зальем экран синим цветом методом Clear. В параметрах передаем, что нужно очистить весь задний буфер [0, NULL, D3DCLEAR_TARGET] цветом [D3DCOLOR_XRGB(100, 149, 237)], остальные параметры значения пока не имеют. Теперь выведем содержимое заднего буфера на экран функцией Present и посмотрим на результат.
void Render()
{
 device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(100, 149, 237), 1.0f, 0);
 device->Present(NULL, NULL, NULL, NULL);
}

Завершение работы

В любом приложении выделенные ресурсы должны быть освобождены по окончании работы. Так как объекты DirectX Graphics являются COM компонентами, то это делается методом Release.
void ReleaseDirect3D()
{
 device->Release();
 d3d->Release();
}

В итоге у нас получилось приложение, которое представляет из себя окно, залитое синим цветом.
Исходный текст примера можно скачать здесь

В конце каждого выпуска я привожу справочник по всем новым интерфейсам, типам, функциям и т.д. затронутым в статье. Полную версию справочника можно будет посмотреть на сайте, который вот-вот откроется.


Direct3DCreate9

Создает экземпляр интерфейса IDirect3D9.
IDirect3D9 *Direct3DCreate9(
    UINT SDKVersion
);

Параметры

SDKVersion
Всегда D3D_SDK_VERSION

Возвращаемое значение

В случае успеха функция возвращает указатель на экземпляр интерфейса IDirect3D9, в противном случае NULL.

Пример

LPDIRECT3D9 d3d;
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d == NULL)
{
    //Ошибка
}

D3DDEVTYPE

Типы устройств, используемых для вывода графики.
typedef enum D3DDEVTYPE
{
    D3DDEVTYPE_HAL     = 1,
    D3DDEVTYPE_NULLREF = 4,
    D3DDEVTYPE_REF     = 2,
    D3DDEVTYPE_SW      = 3,
} D3DDEVTYPE, *LPD3DDEVTYPE;
D3DDEVTYPE_HAL
использовать аппаратное ускорение для вывода графики.
D3DDEVTYPE_REF
Программная эмуляция. Используется для эмуляции функциональности не поддерживаемой видеокартой.
D3DD3DDEVTYPE_SW
Программная эмуляция средствами сторонних разработчиков.
D3DDEVTYPE_NULLREF
Нуль-устройство, игнорирующее все поступающие команды. Может использоваться для оценки производительности программы на бесконечно быстрой видеокарте.

D3DCREATE

Флаги, задающие режим работы устройства.
D3DCREATE_FPU_PRESERVE
Увеличение точности вычислений при выводе графики.
D3DCREATE_HARDWARE_VERTEXPROCESSING
Аппаратная обработка вершин.
D3DCREATE_SOFTWARE_VERTEXPROCESSING
Программная обработка вершин.
D3DCREATE_MIXED_VERTEXPROCESSING
Смешанная обработка вершин.
D3DCREATE_MULTITHREADED
Должен быть установлен если устройство используется несколькими потоками
D3DCREATE_NOWINDOWCHANGES
Означает, что окно используемое DirectX Graphics никогда не теряет фокус. Если установлен этот флаг, приложение должно полностью взять на себя управлением фокусом окна. В том числе нажатие ALT + TAB и клики мышки.

IDirect3D9

Используется приложениями для того, чтобы создавать объекты DirectX Graphics. Также этот интерфейс содержит методы для перечисления возможностей и характеристик устройств, отвечающих за вывод графики. Это первый интерфейс, экземпляр которого должен быть создан приложением, чтобы использовать возможности DirectX Graphics.

Создание

Функция Direct3DCreate9

Методы

CreateDevice

Создает экземпляр класса IDirect3DDevice9, который содержит в себе все методы для работы с графикой.
HRESULT CreateDevice(
    UINT                   Adapter,
    D3DDEVTYPE             DeviceType,
    HWND                   hFocusWindow,
    D3DCREATE              BehaviorFlags,
    D3DPRESENT_PARAMETERS* pPresentationParameters,
    IDirect3DDevice9**     ppReturnedDeviceInterface
);
Параметры
Adapter
[in] Порядковый номер видеокарты. Видеокарта по умолчанию D3DADAPTER_DEFAULT.
DeviceType
[in] Тип устройства, используемого для вывода графики.
hFocusWindow
[in] Дескриптор главного окна, это окно будет переключаться в полноэеранный режим.
BehaviorFlags
[in] Дополнительные флаги, задающие режим работы устройства.
pPresentationParameters
[in, out] Структура, описывающая характеристики создаваемого устройства.
ppReturnedDeviceInterface
[out, ret] Указатель на IDirect3DDevice9.

Возвращаемое значение

D3D_OK
Метод завершился успешно.
D3DERR_DEVICELOST, D3DERR_INVALIDCALL, D3DERR_NOTAVAILABLE, D3DERR_OUTOFVIDEOMEMORY
Метод закончился неудачей.
Пример 1
Оконный режим.
D3DPRESENT_PARAMETERS present;
ZeroMemory(&present, sizeof(present));
present.Windowed = true;
present.SwapEffect = D3DSWAPEFFECT_DISCARD;

d3d->CreateDevice(0, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &device);
Пример 2
Полноэкранный режим.
D3DPRESENT_PARAMETERS present;
ZeroMemory(&present, sizeof(present));
present.Windowed = false;
present.BackBufferWidth = 800;
present.BackBufferHeight = 600;
present.BackBufferFormat = D3DFMT_X8R8G8B8;
present.SwapEffect = D3DSWAPEFFECT_DISCARD;

d3d->CreateDevice(0, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &device);

D3DPRESENT_PARAMETERS

Структура, описывающая параметры вывода графики
typedef struct D3DPRESENT_PARAMETERS {
    UINT                BackBufferWidth, BackBufferHeight;
    D3DFORMAT           BackBufferFormat;
    UINT                BackBufferCount;
    D3DMULTISAMPLE_TYPE MultiSampleType;
    DWORD               MultiSampleQuality;
    D3DSWAPEFFECT       SwapEffect;
    HWND                hDeviceWindow;
    BOOL                Windowed;
    BOOL                EnableAutoDepthStencil;
    D3DFORMAT           AutoDepthStencilFormat;
    D3DPRESENTFLAG      Flags;
    UINT                FullScreen_RefreshRateInHz;
    UINT                PresentationInterval;
} D3DPRESENT_PARAMETERS, *LPD3DPRESENT_PARAMETERS;

Поля

BackBufferWidth, BackBufferHeight
Длинна и ширина заднего буфера. В полноэкранном режиме задает разрешение экрана.
BackBufferFormat
Формат заднего буфера. В полноэкранном режиме задает формат экрана.
BackBufferCount
Количество задних буферов.
MultiSampleType
Тип антиализинга.
MultiSampleQuality
Качество антиализинга.
SwapEffect
Метод обмена буферами при выводе изображения.
hDeviceWindow
Дескриптор окна, в которое будет выводиться изображение.
  • В полноэкранном режиме главное окно.
  • В оконном режиме если параметр равен NULL, то для вывода берется главное окно.
Windowed
Если значение этого поля FALSE, то приложение запустится в полноэкранном режиме, в противном случае в оконном.
EnableAutoDepthStencil
Если TRUE, то используются буфер глубины и stencil буфер.
AutoDepthStencilFormat
Формат буфера глубины и stencil буфера.
Flags
Дополнительные флаги.
FullScreen_RefreshRateInHz
Частота вертикальной развертки монитора.

D3DFORMAT

Возможные форматы буферов
typedef enum _D3DFORMAT {
 ... (values) 
} D3DFORMAT;

Форматы заднего буфера и экрана

D3DFMT_A2R10G10B10
32-bit формат с альфа каналом, по 10 бит на каждую составляющую цвета и 2 бита на альфа канал. Только полноэкранный режим.
D3DFMT_A8R8G8B8
32-bit формат с альфа каналом, по 8 бит на каждую составляющую цвета и 8 бит на альфа канал. Только задний буфер.
D3DFMT_X8R8G8B8
32-bit формат, по 8 бит на каждую составляющую цвета.
D3DFMT_A1R5G5B5
16-bit формат с альфа каналом, по 5 бит на каждую составляющую цвета и 1 бит на альфа канал. Только задний буфер.
D3DFMT_X1R5G5B5
16-bit формат, по 5 бит на каждую составляющую цвета
D3DFMT_R5G6B5
16-bit формат, 6 бит на синюю составляющую и по 5 бит на остальные

Форматы буфера глубины и stencil буфера

D3DFMT_D16_LOCKABLE
16-bit буфер глубины
D3DFMT_D32
32-bit буфер глубины
D3DFMT_D15S1
16-bit буфер, 15 бит для буфера глубины и 1 бит для stencil буфера
D3DFMT_D24S8
32-bit буфер, 24 бит для буфера глубины и 8 бит для stencil буфера
D3DFMT_D24X8
32-bit буфер, 24 бит для буфера глубины
D3DFMT_D24X4S4
32-bit буфер, 24 бит для буфера глубины и 4 бит для stencil буфера
D3DFMT_D32F_LOCKABLE
32-bit буфер, 32 бит для буфера глубины в формате плавующей точки
D3DFMT_D24FS8
32-bit буфер, 24 бит для буфера глубины в формате плавующей точки и 8 бит для stencil буфера
D3DFMT_D16
16-bit буфер глубины

Форматы вершинных и индексных буферов

D3DFMT_VERTEXDATA
Вершинный буфер
D3DFMT_INDEX16
16-bit индексный буфер
D3DFMT_INDEX32
32-bit индексный буфер

Прочие форматы

D3DFMT_UNKNOWN
Неизвестный формат

D3DMULTISAMPLE_TYPE

Уровни антиализинга
typedef enum D3DMULTISAMPLE_TYPE
{
    D3DMULTISAMPLE_NONE        = 0,
    D3DMULTISAMPLE_NONMASKABLE = 1,
    D3DMULTISAMPLE_2_SAMPLES   = 2,
    D3DMULTISAMPLE_3_SAMPLES   = 3,
    D3DMULTISAMPLE_4_SAMPLES   = 4,
    D3DMULTISAMPLE_5_SAMPLES   = 5,
    D3DMULTISAMPLE_6_SAMPLES   = 6,
    D3DMULTISAMPLE_7_SAMPLES   = 7,
    D3DMULTISAMPLE_8_SAMPLES   = 8,
    D3DMULTISAMPLE_9__SAMPLES  = 9,
    D3DMULTISAMPLE_10_SAMPLES = 10,
    D3DMULTISAMPLE_11_SAMPLES = 11,
    D3DMULTISAMPLE_12_SAMPLES = 12,
    D3DMULTISAMPLE_13_SAMPLES = 13,
    D3DMULTISAMPLE_14_SAMPLES = 14,
    D3DMULTISAMPLE_15_SAMPLES = 15,
    D3DMULTISAMPLE_16_SAMPLES = 16,
} D3DMULTISAMPLE_TYPE, *LPD3DMULTISAMPLE_TYPE;

D3DSWAPEFFECT

Способы обмена буферами при выводе изображения
typedef enum D3DSWAPEFFECT
{
    D3DSWAPEFFECT_DISCARD = 1,
    D3DSWAPEFFECT_FLIP    = 2,
    D3DSWAPEFFECT_COPY    = 3,
} D3DSWAPEFFECT, *LPD3DSWAPEFFECT;
D3DSWAPEFFECT_FLIP
Самый быстрый способ. Заключается в том, что видеокарте просто дается указание выводит изображение из заднего буфера. При таком методе обмена, изображение выводится на экран моментально. Работает только в полноэкранном режиме.
D3DSWAPEFFECT_COPY
Изображение копируется из заднего буфера в область экрана.
D3DSWAPEFFECT_DISCARD
Используется для отладки. При обмене буферов задний буфер затирается и в него записывется мусор.

D3DPRESENTFLAG

D3DPRESENTFLAG_DEVICECLIP
Обрезать область вывода графики до клиентской части окна. Работает только в Windows 2000 и Windows XP
D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
Используется при отладке. После вывода графики содержимое буферов глубины и z-буферов заполняется мусором.
D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
Если приложение планирует осуществлять прямой доступ к заднему буферу, нужно установить этот флаг.
D3DPRESENTFLAG_VIDEO
Является подсказкой драйверу, что задний буфер содержит видео информацию.

IDirect3DDevice9

Используется приложением для вывода графики, работы с ресурсами, цветовой гаммой, палитрами и шейдерами.

Создание

Метод CreateDevice.

Методы

Clear

Очищает буферы вывода графики (задний буфер, буфер гдубины и stencil буфер).
HRESULT Clear(
    DWORD          Count,
    CONST D3DRECT* pRects,
    D3DCLEAR       Flags,
    D3DCOLOR       Color,
    float          Z,
    DWORD          Stencil
);

Параметры

Count
Количество прямоугольников в массиве pRects. Если 0, то очищается весь буфер.
pRects
Указатель на массив прямоугольников, указывающих область для очистки.
Flags
Комбинация флагов, указывающая какие буферы очищать.
Color
Задний буфер будет заполнен этим цветом.
Z
Буфер глубины будет заполнен этим значением. Допустимые значения от 0 до 1. Обычно 1.
Stencil
Stencil буфер будет заполнен этим значением. Допустимые значения от 0 до 2n - 1, где n - количество бит, выделенных под stencil буфер. Обычно 0.

Возвращаемое значение

D3D_OK
Метод завершился успешно.
D3DERR_INVALIDCALL
Метод закончился неудачей.

Пример

device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_XRGB(100, 149, 237), 1.0f, 0);

Present

Выводит на экран содержимое заднего буфера.
HRESULT Present(
    CONST RECT*    pSourceRect,
    CONST RECT*    pDestRect,
    HWND           hDestWindowOverride,
    CONST RGNDATA* pDirtyRegion
);

Параметры

pSourceRect
Указатель на прямоугольник заднего буфера для отображения. Если NULL, то отображается весь буфер.
pDestRect
Указатель на прямоугольник экрана для отображения. Если размеры pSourceRect и pDestRect не совпадают, DirectX Graphics масштабирует изображение. Если NULL, то используется весь экран.
hDestWindowOverride
Окно для вывода изображения. Если NULL, то используется главное окно.

Возвращаемое значение

D3D_OK
Метод завершился успешно.
D3DERR_DEVICELOST, D3DERR_DRIVERINTERNALERROR, D3DERR_INVALIDCALL
Метод закончился неудачей.

Пример

device->Present(NULL, NULL, NULL, NULL);

D3DRECT

Прямоугольник
typedef struct D3DRECT {
    LONG x1, y1;
    LONG x2, y2;
} D3DRECT, *LPD3DRECT;

Поля

x1, y1
Координаты верхнего левого угла прясоугольника.
x2, y2
Координаты нижнего правого угла прясоугольника.

D3DCLEAR

D3DCLEAR_TARGET
Очистить задний буфер.
D3DCLEAR_ZBUFFER
Очистить буфер глубины.
D3DCLEAR_STENCIL
Очистить stencil буфер.


В избранное