![]() | ||||||||||||||||||||||||||||||
![]() |
![]() |
|
|
|||||||||||||||||||||||||||
![]() |
|
Программирование с использованием DirectX9Источник: sources orb
От автора. Эта статья посвящена основам программирования трехмерных приложений на С++ и использованию библиотеки DirectX 9. ВведениеПричиной появления библиотеки DirectX явилась медлительность стандартных графических средств ОС Windows. Кроме того, разработчику сложно предугадать оборудование пользователя, который будет играть в игру, тем более что в наше время оборудование обновляется чуть ли не каждый день. Выходом из ситуации стала разработка библиотек для работы с графикой. Наиболее популярные - OpenGL и DirectX. Выбора между этими библиотеками делать не будем. Многие специалисты отдают предпочтение OpenGL, другие DirectX. На форумах и конференциях идут обсуждения, перечисляются преимущества и недостатки каждой. OpenGL - Open Graphic Library, открытая графическая библиотека. Термин "открытый" означает "независимый от производителей". Библиотеку OpenGL могут производить разные фирмы и отдельные разработчики, главное, чтобы она удовлетворяла спецификации (стандарту) OpenGL и ряду тестов. Процедуры OpenGL работают как с растровой, так и с векторной графикой и позволяют создавать двух- и трехмерные объекты произвольной формы. Для объекта может быть задан материал и наложена растровая текстура. Объектами сцен также являются источники света. Вдобавок в библиотеке OpenGL имеются средства взаимодействия графических объектов, которые позволяют создавать эффекты прозрачности, тумана, смешивания цветов, выполнять логические операции над объектами, передвигать объекты сцены, лампы и камеры по заданным траекториям и т.д. DirectX - это мультимедийная библиотека, позволяющая напрямую работать с аппаратным обеспечением компьютера в обход традиционных средств платформы Win32. Вся DirectX делится на компоненты, отвечающие за ту или иную часть работы библиотеки: DirectX Graphics - объединяет компоненты DirectDraw и Direct3D для работы с двух- и трёхмерной графикой. Библиотека спроектирована так, что она может использовать все аппаратные возможности видеокарты по обработке графики. Если какие-то требуемые возможности не реализованы аппаратно, то они эмулируются программно. Рассмотрим подробнее DirectX.DirectX включает в себя уровень абстракции - HAL (Hardware Abstraction Layer). С помощью HAL происходит взаимодействие приложения с оборудованием компьютера, вне зависимости от изготовителя оборудования. Это дает возможность написанному коду работать на любом аппаратном обеспечении без внесения параметров этого оборудования.
![]() Вся библиотека DirectX построена на основе СОМ (Component Object Model). Вам не придется углубляться в сущность этой технологии, так как вся работа с СОМ основана на вызовах соответствующих функций. В составе СОМ имеется API, называемая СОМ-библиотекой; с её помощью достигается управление всеми компонентами. Каждый из программных компонентов реализует определенное количество СОМ-объектов, доступ к которым осуществляется посредством интерфейсов, которые, в свою очередь состоят из функций. С помощью этих функций и происходит взаимодействие с СОМ-объектом. Построение сценыПрежде чем начать программировать, нужно четко представлять схему построения сцены.
Конечно, на эти этапы делить создание трехмерного приложения можно только условно, но все же такое разложение помогает понять в общих чертах создание приложения. Создание оконного приложенияПрежде чем приступить к программированию графики с помощью DirectX, необходимо создать каркас программы. Каркас приложения это самое простое Windows приложение, его описание пропустим из-за того, что оно рассмотрено во всех книгах программирования под Windows, и описание можно найти на многих сайтах в Интернете. Главное отличие - это вывод на экран, мы не используем сообщение while(msg.message!=WM_QUIT) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); }else RenderScene(); } Создаем цикл, выход из которого возможен при получении сообщения Инициализация DirectXДля начала необходимо подключить заголовочный файл. #pragma comment(lib, "d3d9.lib") Создадим функцию, в которой будут инициализироваться интерфейсы DirectX: bool InitDirectX(void). Создаем глобальные переменные: Для удобства создадим функцию bool InitDirectX(void) { if((pDirect3D=Direct3DCreate9(D3D_SDK_VERSION)) == NULL) return(false); D3DDISPLAYMODE stDisplay; if(FAILED(pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &stDisplay))) return(false); D3DPRESENT_PARAMETERS Direct3DParametr; ZeroMemory(&Direct3DParametr, sizeof(Direct3DParametr)); Direct3DParametr.Windowed=TRUE; Direct3DParametr.SwapEffect=D3DSWAPEFFECT_DISCARD; Direct3DParametr.BackBufferFormat=stDisplay.Format; if(FAILED(pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &Direct3DParametr, &pDirectDevice))) return(false); return(true); }
Для проверки результата выполнения функции используется макрос if(FAILED(…)) { сбой } else { функция выполнена успешно } также можно использовать макрос SUCCEEDED, по такой схеме if(SUCCEEDED(…)) { функция выполнена успешно } else { сбой } Теперь нужно получить текущие параметры дисплея с помощью функции
Создаем объект интерфейса
Функция для рендеринга сценыВ этой части кода происходит вывод изображения на экран void RenderScene(void) { if(pDirectDevice==NULL) return; pDirectDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 192, 0), 1.0f, 0); pDirectDevice->BeginScene(); pDirectDevice->EndScene(); pDirectDevice->Present(NULL, NULL, NULL, NULL); } Сначала необходимо очистить задний буфер и заполнить все пространство одним цветом: Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 192, 0), 1.0f, 0) Создание сцены происходит между строками: pDirectDevice->BeginScene(); pDirectDevice->EndScene(); Все что в этом блоке, прорисовывается в заднем буфере. pDirectDevice->Present(NULL, NULL, NULL, NULL) На данный момент у нас есть полностью работоспособная оболочка для создания 3D приложения. Создать новый проект Win32, Empty и добавить этот файл (window1.cpp). Можно компилировать и запускать (для выхода нужно нажать любую клавишу). Так как мы ничего не рисовали, то на экране нет ни одного объекта. Все что было проделано это инициализация устройств и очистка экрана в темно-зеленый цвет. Насладившись результатами работы, нажимаем любую кнопку для выхода из программы и приступаем к рисованию объектов. Создание объектаЕсли посмотреть на схему создания 3D сцены, получится что пропущены шаги - создание объекта и применение материалов с освещением. Освещение и материалы прибережем на следующую статью, а объект создать нужно!
![]() Получилось 7 треугольников. Каждый треугольник имеет кроме координат 3х вершин еще и параметр преобразования и цвет вершины, поэтому создадим структуру, которая будет определять все характеристики вершин: struct CUSTOMVERTEX //формат вершин { FLOAT x, y, z, rhw; DWORD color; }; С помощью строки: #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW/D3DFVF_DIFFUSE) описывается формат содержания вершин в отдельном потоке данных. Здесь применяется гибкий формат вершин - FVF (Flexible Vertex Format). Все перечисленные элементы совпадают с объявленными в структуре. bool InitBufferVertex(void); Все вершины будут храниться в буфере вершин. При заполнении буфера данными его необходимо предварительно заблокировать, после заполнения данным - разблокировать. LPDIRECT3DVERTEXBUFFER9 pBufferVertex=NULL; И введем координаты всех вершин в формате структуры:
Создаем буфер вершин: CreateVertexBuffer(21*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &pBufferVertex, NULL) указываем размер, формат и передаем указатель, где будет храниться информация. if(FAILED(pBufferVertex->Lock(0, sizeof(stVertex), (void**)&pBV, 0))) return(false); memcpy(pBV, stVertex, sizeof(stVertex)); pBufferVertex->Unlock(); //разблокировать буфер для дальнейшей работы Рендеринг объектаВывод всех объектов сцены на экран происходит в функции рендеринга между строками pDirectDevice->BeginScene(); pDirectDevice->EndScene(); Заполним этот промежуток. SetStreamSource(0, pBufferVertex, 0, sizeof(CUSTOMVERTEX)); SetFVF(D3DFVF_CUSTOMVERTEX); // задаем формат вершин Выводим объект, для этого используем функцию вывода примитивов (примитив - любая геометрическая фигура). DrawPrimitive(D3DPT_TRIANGLELIST, // что рисовать 0, // индекс первой вершины 7 // количество выводимых объектов ); Готово!!! (листинг программы heart.cpp) Примечание: При написании статьи я умышленно опустил детальное описание функций, что бы не нагружать ненужной пока информацией. Полное описание использованных функций можно найти в приложении к статье или других источниках, например, MSDN.
Ссылки по теме
|
|