Войти
ПрограммированиеСтатьиГрафика

Direct3D9: Урок 1: Создание D3D Устройства.

Автор:

Шаг 1: Создание окна
Шаг 2: Инициализация D3D
Шаг 3: Система сообщений
Шаг 4: Рендеринг и отображение сцены
Шаг 5: Закрытие

Шаг 1: Создание окна

Первая вещь, которую любое Windows приложение должно сделать при запуске - это создать окно для отображения на экране. Сделав это, наш проект начинает выполнение с функции WinMain(). Следующий код выполняет инициализацию окна.

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
  // Регистрируем класс окна
  WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, OL, OL,
                                    GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                                    "D3D Tutorial", NULL };
  RegisterClassEx( &wc );
  // Создаём окно приложения
  HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 01: Создание устройства",
                            WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                            GetDesktopWindow(), NULL, wc.hInstance, NULL );
}

Предыдущий код является примером стандартного Windows программирования. Пример начинается с определения и регистрации класса окна. После того, как класс зарегистрирован, код создаёт простое окно, использующее зарегистрированные классы, с клиентской областью 300x300 пикселей. У этого окна нет меню или дочерних форм. Пример использует для создания окна стиль WS_OVERLAPPEDWINDOW, который включает в себя кнопки управления Свернуть, Развернуть и Закрыть. (Если пример запускается в полноэкранном режиме, предпочтительней будет использовать стиль WS_EX_TOPMOST, который специфичен для ситуации, когда окно располагается по всему экрану вплоть до деинициализации). Когда окно создано, код нашего примера вызывает стандартные Win32 функции, чтобы показать и обновить окно.

Шаг 2: Инициализация D3D

Проект Создание устройства выполняет инициализацию Direct3D в определённой функции, вызываемой из Win Main после создания окна. После того, как вы создадите окно приложения, вы можете инициализировать Direct3D объект, который вы хотите использовать для рендеринга в сцене. Этот процесс включает в себя создание объекта, настройку параметров визуализации и финальное создание Direct3D устройства.

После создания Direct3D объекта используйте метод IDirect3D9::CreateDevice для создания устройства, пронумерованных устройств, типов, модов и т.д.

if(NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION) ) )
    return E_FAIL;

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

По наполнению поля D3DPRESENT_PARAMETERS вы можете определить, как будет вести себя ваше 3-D приложение. В нашем проекте мы выбираем оконный режим в TRUE, SwapEffect в D3DSWAPEFFECT_DISCARD, и BackBufferFormat в D3DFMT_UNKNOWN.

D3DPRESENT_PARAMETERS d3dpp; 
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

Финальный шаг в использовании метода IDirect3D9::CreateDevice состоит в создании Direct3D устройства, который иллюстрирует следующий код.

if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                  D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                  &d3dpp, &g_pd3dDevice ) ) )

Предшествующий код показывал, как создать устройство с использованием стандартного адаптера при использовании флага D3DADAPTER_DEFAULT. В большинстве случаев в системе есть только один видеоадаптер, если не стоит вторая видеокарта. Укажите, что вы предпочитаете аппаратные средства программным, определяя D3DDEVTYPE_HAL для параметра DeviceType. Этот код использует D3DCREATE_SOFTWARE_VERTEXPROCESSING, чтобы сообщить системе, что она должна использовать программную обработку вершин. Обратите внимание, что если вы говорите системе использовать аппаратную обработку вершин, определяя  D3DCREATE_HARDWARE_VERTEXPROCESSING, вы получите существенное увеличение производительности на видеокартах, которые поддерживают аппаратную обработку вершин.

Шаг 3: Система сообщений

После того, как вы создадите окно вашего приложения и инициализируете Microsoft Direct 3D, вы можете произвести рендеринг сцены. В большинстве случаев, Windows приложения контролируют сообщения системы в своей петле сообщений, и они перерисовывают кадры, когда в очереди нет никаких сообщений. Однако наш проект ждёт, пока сообщение WM_PAINT не окажется в очереди, сообщая программе о необходимости перерисовать все части или часть окна.

// Петля сообщений
MSG msg; 
while( GetMessage( &msg, NULL, 0, 0 ) )
{
    TranslateMessage( &msg );
    DispatchMessage( &msg );
}

Всё время, когда петля сообщений работает DispatchMessage вызывает MsgProc, который обрабатывает сообщения в очереди. Когда WM_PAINT стоит в очереди, приложение вызывает Рендеринг, чтобы произвести перерисовку окна. Тогда вызывается Win32 функция ValidateRect, чтобы перерисовать клиентскую область.

Типичный код для обработки сообщений показан ниже.

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            PostQuitMessage( 0 );
            return 0;
        case WM_PAINT:
            Render();
            ValidateRect( hWnd, NULL );
            return 0;
    }
    return DefWindowProc( hWnd, msg, wParam, lParam );
}

Шаг 4: Рендеринг и отображение сцены

Чтобы произвести рендеринг и показ сцены, код нашего примера очищает back buffer в синий цвет и копирует содержимое back buffer'a в первичный буфер, и выводит первичный буфер на экран.

Для очистки сцены вызываем метод IDirect3DDevice9::Clear().

// Очищаем back buffer в синий цвет
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );

Первые два параметра, принятые в IDirect3DDevice9::Clear сообщают Direct3D размер и адрес массива прямоугольников, которые будут очищены. Массив прямоугольников описывает области рендеринга на главной поверхности, которая должна быть очищена.

В большинстве случаев вы используете единственный прямоугольник, который охватывает всю поверхность рендеринга. Вы делаете это, определив первый параметр как 0, а второй  как NULL. Третий параметр определяет поведение метода. Вы можете определить флаг для очистки поверхности, буфера глубины, буфера трафарета или любой комбинации из этих трёх параметров. В этом туториале не используется буфер глубины, так - что единственным используемым флагом будет D3DCLEAR_TARGET. Последние три параметра установлены, чтобы отразить очистку параметров для цели рендеринга, буфера глубины и буфера трафарета. В проекте устанавливается цвет очистки поверхности в синий (D3DCOLOR_XRGB(0,0,255)). Последние два параметра игнорируются методом IDirect3DDevice9::Clear потому, что соответствующие флаги не присутствуют.

После очистки порта просмотра, проект сообщает Direct3D, что обновление сцены начнётся, когда Direct3D сигнализирует, что рендеринг объектов закончился, как показано в следующем фрагменте кода.

// Начало сцены
g_pd3dDevice->BeginScene();

// Рендеринг объектов сцены находится здесь

// Конец сцены
g_pd3dDevice->EndScene();

Методы IDirect3DDevice9::BeginScene и IDirect3DDevice9::EndScene говорят системе, когда рендеринг начнётся или закончится. Вы можете вызвать методы рендеринга только между вызовами этих методов. Даже если методы рендеринга не сработали, вы должны вызвать EndScene прежде, чем опять вызывать BeginScene.

После рендеринга сцены, вы должны показать её с помощью функции IDirect3DDevice9::Present.

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

Первые два параметра принятые функцией Present - исходные прямоугольник и предназначенный прямоугольник. Наш код копирует содержание заднего буфера в передний, уравняв эти два параметра к NULL. Третий параметр устанавливает окно для презентации. Поскольку этот параметр установлен пустым, hWndDeviceWindow, являющийся членом D3DPRESENT_PARAMETERS, используется. Четвёртый параметр DirtyRegion в большинстве случаев должен быть установлен в NULL.

Шаг 5: Закрытие

Иногда во время работы ваша программа должна закрыться. Закрытие DirectX приложения означает не только уничтожение окна, но и освобождение любого DirectX объекта, используемого вашей программой, так - же, как и указателей на них. Наш проект вызывает функцию Cleanup, и определённая в приложении функция вызывает сообщение WM_DESTROY.

VOID Cleanup()

{
    if( g_pd3dDevice != NULL)
        g_pd3dDevice->Release();
    if( g_pD3D != NULL)
        g_pD3D->Release();
}

Предыдущая функция освобождает DirectX объекты, используя для этого вызов метода IUnknown::Release для освобождения каждого объекта. Поскольку этот туториал следует правилам COM, рекомендуется, чтобы ссылки для большинства объектов стали нулём, и автоматически удалены из памяти.

В дополнении к завершению, во время нормального выполнения, когда пользователь изменяет разрешение экрана или глубину цвета, вы, возможно, должны уничтожить и обновить используемые Direct3D объекты. Поэтому, это хорошая идея, чтобы держать код закрытия приложения в одном месте, которое можно вызвать при необходимости.

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

Исходный код урока: d3d9_tut1.zip.

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

#Direct3D, #основы, #уроки

16 апреля 2003 (Обновление: 29 сен. 2009)

Комментарии [55]