Россия, г. Кострома |
Двумерная графика с использованием Direct3D
Следующим шагом является получение текущих установок рабочего стола, а именно, какой формат пикселя (сколько битов отведено под каждую составляющую цвета) присутствует в данный момент. Для этого можно воспользоваться, вызвав метод GetAdapterDisplayMode главного объекта Direct3D. Примеры вызовов этого метода для языков C++ и Pascal приведены в следующей таблице:
C++ |
D3DDISPLAYMODE display; … direct3d ->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &display ); |
Pascal |
var display: TD3DDisplayMode; … direct3d.GetAdapterDisplayMode( D3DADAPTER_DEFAULT, display ); |
У метода GetAdapterDisplayMode имеются два аргумента:
- константа, определяющая номер (индекс) видеоадаптера, для которого запрашиваются параметры;
- указатель на переменную, в которую помещается результат выполнения команды.
Если у вас в системе присутствует всего один видеоадаптер, то в качестве первого параметра можно передавать ноль. Второй аргумент представляет собой переменную структурного типа следующего содержания:
C++ |
typedef struct _D3DDISPLAYMODE { UINT Width; UINT Height; UINT RefreshRate; D3DFORMAT Format; } D3DDISPLAYMODE; |
Pascal |
TD3DDisplayMode = packed record Width: LongWord; Height: LongWord; RefreshRate: LongWord; Format: TD3DFormat; end {_D3DDISPLAYMODE}; |
Первые два поля данной структуры определяют соответственно ширину и высоту рабочего стола, третье поле содержит частоту обновления монитора, и последнее поле – формат пикселя. Нас интересует только последнее поле этой структуры для того, чтобы использовать текущие установки в механизме двойной буферизации.
Следующий шаг – заполнение структуры D3DPRESENT_PARAMETERS, которая будет задавать параметры поверхности вывода (рендеринга). Для этого необходимо объявить вспомогательную переменную и заполнить ее поля, например, следующим образом:
C++ |
D3DPRESENT_PARAMETERS params; … ZeroMemory( ¶ms, sizeof(params) ); params.Windowed = TRUE; params.SwapEffect = D3DSWAPEFFECT_DISCARD; params.BackBufferFormat = display.Format; … |
Pascal |
var params: TD3DPresentParameters; … ZeroMemory( @params, SizeOf(params) ); params.Windowed := True; params.SwapEffect := D3DSWAPEFFECT_DISCARD; params.BackBufferFormat := display.Format; … |
Здесь приведены строки для минимального набора обязательных действий. Строка ZeroMemory(…) заполняет указанную в качестве первого параметра структуру нулями. Строка "params.Windowed := …" указывает, что вывод будет производиться в некоторое окно. Строка "params.SwapEffect := …" задает режим работы механизма двойной буферизации. И последняя строка "params.BackBufferFormat := …" указывает какой формат буфера будет использоваться.
Следующий шаг инициализационных действий состоит в создании устройства вывода. Это действие реализуется с помощью вызова метода CreateDevice главного объекта:
C++ |
direct3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, ¶ms, &device ) |
Pascal |
direct3d.CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Handle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, @params, device ); |
В результате вызова метода CreateDevice получаем ссылку на интерфейс IDirect3DDevice9, с помощью которого мы будем производить рендеринг сцены. Поясним значения параметров метода CreateDevice. Первый параметр (D3DADAPTER_DEFAULT) указывает номер адаптера, установленного в системе. Второй аргумент метода (D3DDEVTYPE_HAL) определяет тип устройства; значение D3DDEVTYPE_HAL - позволяет использовать аппаратное ускорение на 100%, D3DDEVTYPE_REF – указывает использовать только программные действия (ресурсы центрального процессора). Третий параметр позволяет задать окно (Handle), куда будет производиться вывод сцены. Четвертый аргумент (D3DCREATE_SOFTWARE_VERTEXPROCESSING) указывает, что обработка вершин сцены будет производиться по фиксированным заданным правилам (этот параметр следует указывать, если видеоадаптер не поддерживает архитектуру шейдеров). Предпоследний – пятый параметр хранит параметры создаваемого устройства вывода. И последний аргумент – это имя переменной, в которую при успешном вызове будет помещен результат работы метода.
Таким образом, схему работы библиотеки Direct3D можно представить так.
После того, как все наши инициализации и настройки устройства вывода проведены, наступает заключительный шаг, которой состоит в непосредственном построении и отображении сцены на экране дисплея. Наверно самым простым примером построения сцены является вывод пустого окна, закрашенного определенным цветом. Это можно реализовать с помощью метода Clear, который содержится в интерфейсе IDirect3DDevice9. Этот метод закрашивает задний буфер (BackBuffer) указанным цветом. Программная реализация такого вывода будет следующая:
C++ | device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); |
Pascal | device.Clear(0,nil,D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0, 0); |
Первый параметр метода Clear обозначает количество прямоугольников для очистки области вывода (0 обозначает, что очистке подвергается вся область вывода). Второй параметр представляет собой указатель на массив, содержащий набор величин типа TRect. Каждая отдельная структура указывает, какое место в поверхности вывода следует очищать (значение NULL требует очистки всей поверхности отображения). Третий параметр обозначает что именно (какую поверхность) следует очищать. В данном случае очистке подвергается только поверхность вывода. Кроме этого, метод Clear может использоваться для очистки Z -буфера (константа D3DCLEAR_ZBUFFER ) и буфера трафарета (константа D3DCLEAR_STENCIL ). Четвертый параметр указывает, каким цветом следует заполнять поверхность рендеринга. D3DCOLOR_XRGB(Red,Green,Blue) возвращает цвет из трех составляющих – красного, зеленого и синего цветов. Значения параметров должны лежать в диапазоне [0,…,255]. Предпоследний параметр указывает значение, которым будет заполнен буфер глубины (Z-буфер). Значения этого параметра должны лежать в диапазоне [0.0,…,1.0], где 0 – соответствует ближайшей границе, 1 – дальней. Последний параметр метода задает значение для заполнения буфера шаблона ( Stencil буфера).
Следующий шаг процесса рендеринга – это непосредственный вывод содержимого заднего буфера (BackBuffer) в окно визуализации. Этот шаг еще называют переключением буферов, и осуществляется он с помощью метода Present интерфейса IDirect3DDevice9. Программный код с использованием этого метода выглядит следующим образом:
Интерес здесь представляет, как правило, только третий параметр. Если он равен нулю, то идентификатор окна, в который происходит вывод, берется из ранее установленного, при создании устройства. Все остальные параметры выставляют, как правило, в NULL. Таким образом, минимальный набор инструкций для процедуры рендеринга, состоит в вызове двух методов Clear и Present интерфейса IDirect3DDevice9.
Подытожив все рассмотренные шаги по инициализации и процедуре рендеринга, можно все их представить в виде следующей блок-схемы.
Таким образом, последовательность шагов инициализации библиотеки Direct3D может выглядеть следующим образом:
C++ |
direct3d = Direct3DCreate9( D3D_SDK_VERSION ); direct3d ->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &display ); ZeroMemory( ¶ms, sizeof(params) ); params.Windowed = TRUE; params.SwapEffect = D3DSWAPEFFECT_DISCARD; params.BackBufferFormat = display.Format; direct3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, &device ); |
Pascal |
direct3d := Direct3DCreate9( D3D_SDK_VERSION ); direct3d.GetAdapterDisplayMode( D3DADAPTER_DEFAULT, display ); ZeroMemory( @params, SizeOf(params) ); params.Windowed := True; params.SwapEffect := D3DSWAPEFFECT_DISCARD; params.BackBufferFormat := display.Format; direct3d.CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Handle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, @params, device ); |