netlib.narod.ru | < Назад | Оглавление | Далее > |
Теперь, когда вы познакомились с основами рисования трехмерной графики, пришло время использовать полученные знания на практике. Однако перед этим вам необходимо узнать, как подготовить к работе графическую систему.
В данном разделе я познакомлю вас с компонентами DirectX Graphics, которые будут использоваться в этой книге и покажу как запустить графическую систему и подготовить ее к рисованию.
Direct3D разделяет графический функционал по нескольким COM-объектам. У каждого объекта есть собственное назначение, например объект IDirect3D9 используется для управления всей графической системой в целом, а объект IDirect3DDevice9 применяется для управления процессом визуализации графики на экране.
В этой книге я покажу вам только те объекты, которые перечислены в таблице 2.1; именно эти объекты вы скорее всего будете использовать в вашем проекте игры.
Таблица 2.1. Основные компоненты Direct3D
Компонент | Описание |
IDirect3D9 | Используйте этот объект для сбора информации об установленном графическом оборудовании и инициализации интерфейсов устройств |
IDirect3D9Device9 | Имеет дело непосредственно с аппаратурой трехмерной графики. С ним вы визуализируете графику, управляете ресурсами изображений, создаете и устанавливаете режимы визуализации, фильтры затенения и т.д. |
IDirect3DVertexBuffer9 | Содержит массив данных вершин, используемый для рисования полигонов |
IDirect3DTexture9 | Используйте этот объект для хранения всех изображений, применяемых для рисования граней в трехмерных (и двухмерных) изображениях |
Благодаря упрощению Direct3D, начало использования графической системы это простая задача. Вот четыре общих этапа инициализации и запуска графической системы:
Получение интерфейса Direct3D.
Выбор видеорежима.
Установка метода показа.
Создание интерфейса устройства и инициализация дисплея.
Это очень короткий список! Я же сказал вам, что инициализировать и запустить графическую систему очень просто, так что давайте двигаться дальше и посмотрим как выполняется каждый из этих этапов.
Первый шаг к использованию графики — инициализация объекта IDirect3D9. Выполняется она с помощью функции Direct3DCreate9.
IDirect3D9 *Direct3DCreate9( UINT SDKVersion); // D3D_SDK_VERSION
Единственным аргументом этой функции должна быть константа D3D_SDK_VERSION, указывающая используемую версию SDK. Возвращаемая переменная — это указатель на созданный для вас объект IDirect3D9, или, если при создании объекта Direct3D произошла ошибка, будет возвращен NULL.
Для использования этой функции достаточно объявить экземпляр объекта IDirect3D9 и вызвать саму функцию:
IDirect3D9 g_D3D; // глобальный объект IDirect3D9 if((g_D3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) { // Произошла ошибка }
После того, как объект IDirect3D9 создан, можно использовать его для получения информации о графической системе, которая включает список видеорежимов, которые может поддерживать Direct3D. Фактически, если вы не хотите менять формат, то можете запросить у объекта IDirect3D9 информацию о текущем видеорежиме.
Видеорежимы различаются по разрешению экрана (высоте и ширине в пикселях), глубине цвета (количеству отображаемых цветов) и частоте кадров. Например, вы можете установить разрешение 640 × 480 точек с 16-разрядной глубиной цвета и предлагаемой видеокартой по умолчанию частотой кадров.
Информация о видеорежиме хранится в структуре D3DDISPLAYMODE.
typedef struct _D3DDISPLAYMODE { UINT Width; // Ширина экрана в пикселях UINT Height; // Высота экрана в пикселях UINT RefreshRate; // Частота кадров (0 = по умолчанию) D3DFORMAT Format; // Формат цвета } D3DDISPLAYMODE;
Относительно высоты, ширины и частоты кадров все ясно, но что насчет формата цвета? В графике вы обычно выбираете сколько бит будет использоваться в одном пикселе (16, 24 или 32) для хранения информации о цвете. Чем больше битов используется, тем больше цветов можно отобразить (и тем больше потребуется памяти).
Цветовые режимы обычно различаются по количеству битов, отводимых для каждого компонента цвета (красного, зеленого, синего и, возможно, альфа). Возьмем к примеру 16-разрядный цветовой режим — 5 бит для красного, 5 бит для зеленого, 5 бит для синего и один бит для альфа-канала. 5 бит для хранения позволяют использовать 32 оттенка каждого компонента. Для альфа-канала используется один бит, который может быть либо установлен, либо сброшен.
Когда вы ссылаетесь на цветовой режим, вам недостаточно только сказать, что он 16-разрядный, а надо указать количество битов для компонентов цвета, например 1555 (1 для альфа, 5 для красного, 5 для зеленого и 5 для синего). Стандартными цветовыми режимами являются 555 (5 для красного, 5 для зеленого, 5 для синего без альфа-канала), 565 (5 для красного, 6 для зеленого и 5 для синего) и 888 (по 8 бит для каждого компонента). Заметьте, что значение альфа нужно не всегда.
В Direct3D цветовые режимы определены как члены перечисления, представленные в таблице 2.2. На данном этапе предположим, что вы хотите установить видеорежим 640 × 480 и использовать формат цвета D3DFMT_R5G6B5. Вот как в этом случае должна выглядеть инициализация структуры D3DDISPLAYMODE:
D3DDISPLAYMODE d3ddm; d3ddm.Width = 640; d3ddm.Height = 480; d3ddm.RefreshRate = 0; // по умолчанию d3ddm.Format = D3DFMT_R5G6B5;
Таблица 2.2. Константы цветовых режимов в Direct3D
Значение | Формат | Описание |
D3DFMT_R8G8B8 | 24 разряда | 8 красный, 8 зеленый, 8 синий |
D3DFMT_A8R8G8B8 | 32 разряда | 8 альфа, 8 красный, 8 зеленый, 8 синий |
D3DFMT_X8R8G8B8 | 32 разряда | 8 не используется, 8 красный, 8 зеленый, 8 синий |
D3DFMT_R5G6B5 | 16 разрядов | 5 красный, 6 зеленый, 5 синий |
D3DFMT_X1R5G5B5 | 16 разрядов | 1 не используется, 5 красный, 5 зеленый, 5 синий |
D3DFMT_A1R5G5B5 | 16 разрядов | 1 альфа, 5 красный, 5 зеленый, 5 синий |
Чтобы проверить поддерживает ли видеокарта необходимый вам формат цвета, заполните структуру D3DDISPLAYFORMAT информацией о видео режиме и выполните вызов функции:
// g_pD3D = ранее инициализированный объект Direct3D // d3df = ранее инициализированная структура D3DFORMAT // Проверка наличия видеорежима if(FAILED(g_pD3D->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3df, &d3df, FALSE))) { // Ошибка - цветовой режим не поддерживается }
Задание видеорежима подразумевает, что вы работаете в полноэкранном режиме. Если же вы хотите использовать оконный режим (также, как и обычные приложения Windows), Direct3D может предоставить вам информацию об установленном видеорежиме. Для этого предназначен следующий вызов функции:
// g_pD3D = ранее инициализированный объект Direct3D D3DDISPLAYMODE d3ddm; if(FAILED(g_pD3D->GetDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) { // Произошла ошибка }
В случае успешного завершения показанный выше вызов IDirect3D9::GetDisplayMode возвращает заполненную данными структуру D3DDISPLAYMODE.
Следующий этап подготовки Direct3D — определение того, как графика будет показываться пользователю. Вы хотите использовать окно, полный экран или вторичный буфер (о вторичном буфере вы можете прочитать в приведенном ниже примечании)? Какую частоту кадров вы хотите использовать? Вся эта информация (и, как вы увидите, еще и некоторая другая) хранится в структуре D3DPRESENT_PARAMETERS:
typedef struct _D3DPRESENT_PARAMETERS { UINT BackBufferWidth; // Ширина вторичного буфера UINT BackBufferHeight; // Высота вторичного буфера D3DFORMAT BackBufferFormat; // Формат экрана UINT BackBufferCount; // 1 D3DMULTISAMPLE_TYPE MultiSampleType; // 0 D3DSWAPEFFECT SwapEffect; // способ показа // вторичного буфера HWND hDeviceWindow; // NULL BOOL Windowed; // TRUE для оконного режима // FALSE для полноэкранного режима BOOL EnableAutoDepthStencil; // FALSE D3DFORMAT AutoDepthStencilFormat; // 0 DWORD Flags; // 0 UINT FullScreen_RefreshRateInHz; // 0 UINT PresentationInterval; // 0 } D3DPRESENT_PARAMETERS;
Рис. 2.9. Рисование во вторичном буфере скрывает от вас объекты, пока вы не выполните переключение экранов
Хотя данная операция может показаться сложной, вам в действительности не придется иметь дела с большинством полей структуры D3DPRESENT_PARAMETERS; однако вы должны понимать назначение полей, связанных с вторичным буфером.
Вот два варианта инициализации, которые вы можете использовать в зависимости от того, в полноэкранном или в оконном режиме вы собираетесь работать (с небольшим фрагментом, который используется в обоих вариантах):
// d3ddm = ранее инициализированная структура D3DDISPLAYMODE D3DPRESENT_PARAMETERS d3dpp; // Очищаем структуру ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); // Для оконного режима используйте: d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = d3ddm.Format; // используем то же цветовой режим // Для полноэкранного режима используйте: d3dpp.Windowed = FALSE; d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; d3dpp.BackBufferFormat = d3ddm.Format; // используем тот же // цветовой режим // И для оконного и для полноэкранного режима указываем ширину и высоту d3dpp.BackBufferWidth = Width; // Укажите ваше значение ширины d3dpp.BackBufferHeight = Height; // Укажите ваше значение высоты
Наконец вы можете создать интерфейс устройства Direct3D — рабочую лошадку системы трехмерной графики. Чтобы создать и инициализировать интерфейс дисплея вызовите функцию IDirect3D9::CreateDevice, передав ей ранее инициализированные экземпляры структур D3DDISPLAYMODE и D3DPRESENT_PARAMETERS:
HRESULT IDirect3D9::CreateDevice( UINT Adapter, // D3DADAPTER_DEFAULT D3DDEVTYPE DeviceType, // D3DDEVTYPE_HAL HWND hFocusWindow, // дескриптор окна для визуализации DWORD BehaviorFlags, // D3DCREATE_SOFTWARE_VERTEXPROCESSING D3DPRESENT_PARAMETERS *pPresentationParameters, // d3dpp IDirect3DDevice9 *ppReturnedDeviceInterface); // объект устройства
У функции CreateDevice есть параметры для передачи структуры параметров показа, которую вы создали, а также дескриптора окна, принадлежащего вашему приложению (которое Direct3D будет использовать для отображения визуализированной графики). Остальные аргументы достаточно стандартны и вам редко придется менять их значения. Последний аргумент — это указатель на объект устройства Direct3D, который вы создаете. Вызов IDirect3D9::CreateDevice может выглядеть так:
// g_pD3D = ранее инициализированный объект Direct3D // hWnd = дескриптор используемого для визуализации окна // d3dpp = ранее инициализированная структура параметров показа IDirect3DDevice9 *g_pD3DDevice; if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDevice))) { // Произошла ошибка }
Обычно интерфейс устройства функционирует как ожидается и все замечательно работает; графика рисуется и выполняется управление ресурсами памяти. Хотя было бы хорошо думать, что дела будут всегда обстоять подобным образом, это не так. Добро пожаловать в мир потерянных устройств.
Потерей устройства (lost device) называется утрата контроля над графическими ресурсами по какой-либо причине. Может быть, другое приложение получило контроль над видеокартой и освободило память в которой хранились графические ресурсы вашей программы. Возможно, Windows остановила приложение, переведя систему в спящий режим. Независимо от причины вы утратили контроль над видеокартой и вам необходимо вернуть его.
Как узнать что контроль утерян? Проверив значение, возвращаемое любой функцией объекта устройства! Например, далее в этой главе в разделе «Показ сцены», вы увидите как отобразить графику на экране монитора. Если этот вызов возвращает значение D3DERR_DEVICELOST, вы знаете, что устройство потеряно.
Восстановление контроля над устройством это, можно сказать, решительный поступок. Выполняется он с помощью следующей функции:
HRESULT IDirect3DDevice9::Reset( D3DPRESENT_PARAMETERS *pPresentationParameters);
Единственным параметром функции является структура параметров показа, которую вы использовали при инициализации устройства:
// g_pD3DDevice = ранее инициализированный объект устройства // d3dpp = ранее инициализированная структура параметров показа g_pD3DDevice->Reset(&d3dpp);
Я был бы рад сказать, что это волшебная функция, которая сделает за вас все, что необходимо для восстановления устройства, но, к сожалению вынужден сообщить плохие новости. Вызов этой функции выполняет сброс устройства, что приводит к удалению всех ресурсов — на самом деле это не так уж и плохо, потому что есть шанс, что эти ресурсы уже были потеряны (из-за потери устройства).
В результате вы должны заново загрузить все графические ресурсы (такие как текстуры) и восстановить состояние устройства (режимы визуализации). Большинство потерянного — это данные о которых мы еще не говорили, поэтому сейчас мы завершим обсуждение темы.
Работа с Direct3D остается главной задачей. Хотя Microsoft упростила многие интерфейсы, для вас остается много различной работы. Чтобы сократить время разработки приложений Microsoft создала библиотеку D3DX. Библиотека D3DX объединяет различные относящиеся к графике полезные функции, такие как работа с сетками, текстурами, шрифтами, математикой и т.д. В этой книге вы увидите как можно использовать библиотеку D3DX чтобы облегчить процесс разработки игр.
netlib.narod.ru | < Назад | Оглавление | Далее > |