Данный материал взят с сайта old.shatalov.su и является его зеркалом

Создаём компьютерную игру. Создание игр на C++/DirectX

Есть вопросы?
Ошибка на сайте?
рус eng esp
Внимание! Данный сайт не обновляется. Новая версия: shatalov.su

Инициализация Direct2D

Дата создания: 2012-10-22 16:12:19
Последний раз редактировалось: 2012-10-22 16:18:55

    Исходники к уроку:
1. Исходный код инициализации Direct2D

В этом уроке мы настроим нашу заготовку оконного приложения для использования с Direct2D. Главная сегодняшяя цель - уяснить, как происходит инициализация Direct2D. После инициализации мы выведем простую фигуру на экран.

Инициализация Direct2D

Инициализация Direct2D достаточно простая (по сравнению с инициализацией Direct3D :) и включает в себя следующие шаги:

1. Создание фабрики ID2D1Factory.
2. Создание объекта, на который будет происходить вывод графики - ID2D1RenderTarget.
3. Создание инструментов рисования (кисти, изображения). Мы начнём работать с кистями - ID2D1SolidColorBrush.

После этого можно начинать рисовать на объекте, который выводит графику.

Функция D2D1CreateFactory

Как и в других библиотеках DirectX, в Direct2D всё тоже начинается с функции. Сначала нужно создать объект ID2D1Factory (factory - фабрика). Данный объект позволит создавать различные ресурсы Direct2D.

Для выделения памяти под ID2D1Factory исопльзуется функция D2D1CreateFactory. Функция перегруженная, мы будем использовать вариант с двумя аргументами:

!1? template HRESULT D2D1CreateFactory( __in D2D1_FACTORY_TYPE factoryType, __out Factory **factory);?1!

Первый аргумент - тип фабрики: однопоточная, многопоточная. Начнём с однопоточных, поэтому этот параметр будет таким: D2D1_FACTORY_TYPE_SINGLE_THREADED.

Второй аргумент - адрес объекта ID2D1RenderTarget. После вызова функции этот аргумент будет содержать адрес созданной фабрики.

Давайте создадим фабрику. Перед вызовом D2D1CreateFactory нужно объявить интерфейс ID2D1RenderTarget:

!1? ID2D1Factory* factory = NULL; D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,&factory);?1!

Теперь мы можем использовать переменную factory для создания ресурсов.

Создание HwndRenderTarget

Следующая задача - связать окно нашего приложения с Direct2D. Для этого нужно с помощью описателя окна (window handle) создать ресурс HwndRenderTarget (render target - цель вывода графики). Этот ресурс выводит, созданную с помощью него, графику в указанное окно.

HwndRenderTarget создаётся с помощью метода D2D1Factory::CreateHwndRenderTarget:

!1? HRESULT CreateHwndRenderTarget( [ref] const D2D1_RENDER_TARGET_PROPERTIES &renderTargetProperties, [ref] const D2D1_HWND_RENDER_TARGET_PROPERTIES &hwndRenderTargetProperties, [out] ID2D1HwndRenderTarget **hwndRenderTarget );?1!

Первый аргумент - ссылка на заполненную структурную переменную D2D1_RENDER_TARGET_PROPERTIES - свойства ресурса визуализации. Можно автоматически заполнить эту переменную, вызвав функцию RenderTargetProperties. RenderTargetProperties находится в пространстве имён D2D1. Структура D2D1_RENDER_TARGET_PROPERTIES заполняется следующей информацией: формат пикселей, разрешение изображение (dpi) и т.д.

Второй аргумент - ссылка на D2D1_HWND_RENDER_TARGET_PROPERTIES - свойства окна, в которое будет осуществляться вывод графики. Здесь также можно воспользоваться вспомогательной функцией HwndRenderTargetProperties (тоже в пространстве имён D2D1), которая создаст нужную структурную переменную. В функцию нужно передать два параметра: описатель окна и размеры области вывода. Размеры области вывода должны быть в формате D2D1_SIZE_U - эта структура хранит пару целых чисел: ширина, высота. Вы не поверите, но для заполнения этой структуры тоже существует специальная функция - SizeU.

Третий параметр - адрес на объект ID2D1HwndRenderTarget, в котором и будет сохранён ресурс визуализации после выполнения метода:

!1? ID2D1HwndRenderTarget* rt = NULL; factory->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties( hWnd,D2D1::SizeU(rc.right-rc.left, rc.bottom-rc.top)), &rt);?1!

Теперь rt может "рисовать".

Собственно, с инициализацией всё. Давайте теперь посмотрим как происходит рисование.

Создание кисти

В Direct2D кисти представлены интерфейсами ID2D1SolidColorBrush, ID2D1RadialGradientBrush, ID2D1BitmapBrush. Сегодня мы познакомимся с первым - ID2D1SolidColorBrush. Данная кисть закрашивает необходимую область каким-либо цветом.

Кисть ID2D1SolidColorBrush создаётся методом ID2D1RenderTarget::CreateSolidColorBrush. Данный метод перегружен. Мы рассмотрим вариант с двумя аргументами: цвет кисти и адрес создаваемой кисти:

!1? ID2D1SolidColorBrush* rbrush = NULL; rt->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::DarkRed), &rbrush);?1!

Первый аргумент - цвет, заполняется через конструктор класса ColorF - единственный аргумент - константа класса ColorF. Список всех констант можно найти в документации к Direct2D.

После вызова метода CreaeSolidColorBrush у нас всё готово к рисованию.

Рисование прямоугольников в Direct2D

Вывод графики в Direct2D осуществляется между двумя вызовами интерфейса ID2D1HwndRenderTarget: BeginDraw (начать рисование), EndDraw (закончить рисование). В своём коде я расположил эти вызовы в основном цикле после попытки захвата сообщения.

При рисовании сначала нужно очистить область рисования. Для этого используется метод Clear с аргументом - цветом фона:

!1? rt->Clear(D2D1::ColorF(D2D1::ColorF::White));?1!

Direct2D рисует прямоугольники с помощью метода ID2D1RenderTarget::DrawRectangle:

!1? void DrawRectangle( [ref] const D2D1_RECT_F &rect, [in] ID2D1Brush *brush, FLOAT strokeWidth = 1.0f, [in, optional] ID2D1StrokeStyle *strokeStyle = NULL );?1!

Первый аргумент - координаты прямоугольника. Можно заполнить с помощью функции D2D1::RectF. Аргументы: x левого верхнего угла, y левого верхнего угла, x правого нижнего угла, y правого нижнего угла: !1? rt->DrawRectangle(D2D1::RectF(200.0f,200.0f,300.0f,300.0f),rbrush);?1!

В данном случае создаётся прямоугольник размером 100*100. Второй аргумент - кисть, которой будет рисоваться прямоугольник.

Третий и четвёртый аргументы необязательны. Третий - толщина линии, четвёртый - вид линии.

Полный код инициализации Direct2D

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

!1? #include <windows.h> #include <d2d1.h> #pragma comment(lib,"d2d1.lib") LRESULT _stdcall WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); int _stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wc; wc.style = CS_OWNDC; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(6); wc.lpszMenuName = 0; wc.lpszClassName = L"class"; RegisterClass(&wc); HWND hWnd = CreateWindow( L"class", L"Direct2D init", WS_OVERLAPPEDWINDOW,100,100,600,600, NULL,NULL,hInstance,NULL); ID2D1Factory* factory = NULL; D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,&factory); ID2D1HwndRenderTarget* rt = NULL; factory->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties( hWnd,D2D1::SizeU(500,500)) ,&rt); ID2D1SolidColorBrush* rbrush = NULL; rt->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Red), &rbrush); ShowWindow(hWnd,nCmdShow); UpdateWindow(hWnd); MSG msg; while(true) { if(PeekMessage(&msg,0,0,0,PM_REMOVE)) { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } rt->BeginDraw(); rt->Clear(D2D1::ColorF(D2D1::ColorF::White)); rt->DrawRectangle( D2D1::RectF(200.0f,200.0f,300.0f,300.0f), rbrush,100.0f,NULL); rt->EndDraw(); } if (rbrush != NULL) rbrush->Release(); if (rt != NULL) rt->Release(); if (factory != NULL) factory->Release(); return 0; } LRESULT _stdcall WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hWnd,msg,wParam,lParam); } } ?1!

В результате работы этой программы мы увидим окно с красным квадратом посередине.

Direct2D initialization

Завершение программы

Не забывайте, что при завершении программы необходимо освободить все ресурсы:

!1? if (rbrush != NULL) rbrush->Release(); if (rt != NULL) rt->Release(); if (factory != NULL) factory->Release();?1!

Заключение

В данном уроке мы рассмотрели инициализацию Direct2D. В следующих уроках мы рассмотрим различные виды кистей.

На сегодня всё.