Материал: DirectX. Использование возможностей ОС по выводу графики

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

DirectX. Использование возможностей ОС по выводу графики

Содержание


Содержание

Введение

Обзор Direct3D

Работа с интерфейсами

Описание некоторых функций, используемых для работы с Direct3D

Демонстрационная программа

Листинг

Результат выполнения

Заключение

Список литературы

Введение

представляет собой набор технологий и инструментов, которые позволяют создавать разработчику игры и мультимедиа приложения с неслыханным во времена MS-DOS качеством графики и звука. Кроме этого, DirectX служит для обработки клавиатуры, мыши, джойстика, а также для сетевого сообщения.подразделяется на несколько частей, каждая из которых отвечает за что-то свое:

·        DirectDraw - служит для ускорения отображения и обработки двумерной графики

·        Direct3D - для ускорения трехмерной графики

·        DirectSound - работает со звуком - микширование и 3D звук

·        DirectInput - для обработки клавиатуры, мыши, джойстика и так далее

·        DirectPlay - служит в основном для сетевой игрыразрабатывался специально, чтобы превратить платформу Windows как в основную для разработки игр. До этого разработчики использовали только MS-DOS и лишь совсем незначительная часть игр делалась для Windows 3.xx Одной из более ранних попыток Microsoft был выпуск WinG, который позволял разработчикам не писать бесконечные поддержки для различных типов аудио-видеоадаптеров, однако появление DirectX полностью изменило дело в пользу Windows. Теперь, разработчики могли почти не отвлекаться на подержки различных карт, потому что если у карты была поддержка DirectX, то несовместимость больше не была проблемой.- это интефейс довольно низкого уровня. С помощью своих API он предоставляет программисту прямой доступ к памяти адаптеров, где программист может создавать изображение, хранить графические образы, звуки и т. д. За счет непосредственной работы с памятью достигается ускорение, то есть теоретически частота, с которой программист сможет заставить прорисоваваться экран будет зависеть только от частоты, поддерживаемой монитором. Реально же, человек уже слабо воспринимает различия в частоте обновления, если она более 33 FPS (Frame Per Second - кадров в секунду), поэтому будет очень хорошо, если Вы сможете подвести Вашу частоту к этой.

Современные графические адаптеры позволяют доводить FPS двумерной графики до всех разумных пределов, поэтому все задержки с ее отображением от того, что компьютер не успел подготовить новое изображение, а это уже зависит от чатоты процессора и объема оперативной памяти. В трехмерной же графике все сложнее. Здесь скорость отображения зависит как и от мощности компьютера, так и от качества и способности ускорения графической карты. Разработчики видеоускорителей применяют все более и более навороченные технологии ускорения и все для того, чтобы увеличить FPS еще на десяток кадров, а также улучшить качетво картинки (устранить пикселизацию, сгладить цвета...) [6]

Обзор Direct3D

3D - это низкоуровневый графический API (программный интерфейс для приложений), позволяющий отображать трехмерные миры используя аппаратные ускорители трехмерной графики. Direct3D можно представлять как посредника между приложением и графическим устройством (аппаратурой трехмерной графики). Например, чтобы приказать графическому устройству очистить экран, приложение должно вызвать метод Direct3D IDirect3DDevice9::Clear. Взаимоотношения между приложением, Direct3D и аппаратурой компьютера показаны на рис. 1.1.

Рис. 1.1. Взаимосвязь между приложением, Direct3D и аппаратурой

На рис. 1.1 блок с названием Direct3D представляет набор документированных интерфейсов и функций, которые Direct3D предоставляет приложениям и программистам. Эти интерфейсы и функции охватывают полный набор функциональных возможностей, предлагаемых данной версией Direct3D. Обратите внимание, что предложение возможости Direct3D не означает, что она будет поддерживаться аппаратурой.

На рис. 1.1 изображена промежуточная стадия между Direct3D и графическим устройством - уровень абстрагирования от аппаратуры (Hardware Abstraction Layer, HAL). Direct3D не может напрямую взаимодействовать с аппаратурой, поскольку продаются сотни различных видеокарт и каждая видеокарта отличается набором поддерживаемых функций и способом реализации тех функций, которые поддерживаются. Например, две разные видеокарты могут совершенно по-разному выполнять очистку экрана. Поэтому Direct3D требует, чтобы производители оборудования реализовали уровень абстрагирования от оборудования (HAL), который представляет собой зависящий от аппаратуры код, указывающий устройству ка выполнять те или иные операции. Благодаря этому Direct3D не требуется знать специфику конкретных устройств, и его спецификации не зависят от используемого оборудования.

Производители видеокарт встраивают поддержку всех предлагаемых их оборудованием возможностей в HAL. Те возможности, которые предлагает Direct3D, но которые не поддерживает устройство, в HAL не реализованы. Попытка использования тех возможностей Direct3D, которые не реализованы в HAL приводит к ошибке, за исключением тех случаев, когда требуемая функция может быть воспроизведена программно, как , например, программная обработка вершин в библиотеке времени выполнения Direct3D. [4]

Работа с интерфейсами

 основан на технологии COM (Component Object Model - Компонентная Модель Объектов) . Возможно, эта технология имеет ряд преимуществ и упрощает жизнь разработчику подобных продуктов, в данном случае тем, кто разрабатывал DirectX, однако для пользователей это означает дополнительное изучение порядка работы с такой моделью.

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


Из рисунка видно, что имеется указатель на таблицу интерфейсов, каждая ячейка которой в свою очередь содержит указатели на методы того или иного интерфейса в отдельности. Очевидно, что вызов нужного метода напрямую невозможен. Только произведя некоторые манипуляции с указателем, появляется возможность до него добраться. Порядок таких манипуляций можно описать следующими действиями:

. Создать объект

. Получить указатель на соответствующий интерфейс этого объекта.

. Используя данный указатель вызвать нужный метод.

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

Если в языке C++ данный механизм реализован в таком виде:

// Создали объект и получили указатель на интерфейс IDirect3D9

pd3d9 = Direct3DCreate9 (D3D_SDK_VERSION);

// Вызвали метод CreateDeviced9 -> CreateDevice (arg1, arg2, arg3, arg4, arg5, arg6, arg7);

То в ассемблере это будет выглядеть так:

invoke Direct3DCreate9, D3D_SDK_VERSION ; Создали объект

mov pd3d9, eax ; получили указательarg7

push arg6arg5arg4arg3arg2arg1pd3d9eax, pd3d9eax, [eax]dword ptr [eax+3Ch]

Смысл команд, приведенных выше, сводится к занесению данных для метода CreateDevice в стек; получению указателя на таблицу методов, используя указатель на интерфейс; и вызов самого метода CreateDevice. При этом число 3Ch является просто-напросто порядковым номером CreateDevice в таблице указателей на методы, умноженным на четыре.

Подобные операции с вычислением истинного адреса метода способны отбить желание работать на ассемблере с COM моделью. Избежать этого можно используя макрос d3d9.

Программа, которая совершает то же самое, что и указанная выше, но уже с использованием такого макроса:

invoke Direct3DCreate9, D3D_SDK_VERSION ; Создали объектpd3d9, eax ; получили указательd9 CreateDevice, pd3d9, Arg1, ... , Arg7

Макрос автоматически выполняет всю рутинную работу за нас, и вызов метода выглядит почти также как вызов обычной функции API Windows. [5]

Макросы d3dev9, d3dxmesh тем же образом позволяют обращаться к методам соответствующих классов.

Описание некоторых функций, используемых для работы с Direct3D


Исходя из [3]:

Direct3DCreate9,D3D_SDK_VERSION

Direct3DCreate9 - запрос указателя на интерфейс IDirect3D9.

Единственным параметром функции Direct3DCreate9 всегда должна быть константа D3D_SDK_VERSION, гарантирующая, что при построении приложения будут использованы правильные заголовочные файлы. Если при работе функции возникли ошибки, она возвращает нулевой указатель.

CreateDevice, pd3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd ,DCREATE_SOFTWARE_VERTEXPROCESSING,BackBufferWidth, ADDR pd3dDevice

Метод CreateDevice создает объект IDirect3DDevice9.IDirect3D9::CreateDevice(Adapter,DDEVTYPE DeviceType,hFocusWindow,BehaviorFlags,DPRESENT_PARAMETERS *pPresentationParameters,DDevice9** ppReturnedDeviceInterface

);

§   Adapter - указывает физический видеоадаптер, который будет представлять создаваемый объект IDirect3DDevice9.

§   DeviceType - задает тип используемого устройства (т.е. аппаратное устройство (D3DDEVTYPE_HAL) или программное устройство (D3DDEVTYPE_REF)).

§   hFocusWindow - дескриптор окна с которым будет связано устройство. Обычно это то окно, в которое будет выводиться изображение и для наших целей мы здесь задаем тот же дескриптор, который указан в члене d3dpp.hDeviceWindow структуры D3DPRESENT_PARAMETERS.

§   BehaviorFlags - в этом параметре указывается значение D3DCREATE_HARDWARE_VERTEXPROCESSING либо D3DCREATE_SOFTWARE_VERTEXPROCESSING.

§   pPresentationParameters - указывается инициализированный экземпляр структуры D3DPRESENT_PARAMETERS, задающий параметры устройства.

§   ppReturnedDeviceInterface - возвращает указатель на созданное устройство.

D3DXMatrixRotationY, ADDR WorldMatrix, NULLDXMatrixRotationY - Вращение по оси Y.DXMATRIX* D3DXMatrixRotationY(DXMATRIX *pOut,  Angle

);

Параметры:

§  pOut - указатель на структуру D3DXMATRIX, в которую помешается исходный результат операции;

§  Angle - угол вращения в радианах по оси Y

D3DXMatrixRotationZ, ADDR WorldMatrix, RotZ

D3DXMatrixRotationZ - Вращение по оси Z.

D3DXMATRIX* D3DXMatrixRotationZ(DXMATRIX *pOut,    Angle

);

Параметры:

§  pOut - указатель на структуру D3DXMATRIX, в которую помешается исходный результат операции;

§  Angle - угол вращения в радианах по оси Z

D3DXMatrixLookAtLH - вычислить матрицу преобразования вида.

D3DXMATRIX *D3DXMatrixLookAtLH(DXMATRIX* pOut, // указатель на возвращаемую матрицу преобразованияD3DXVECTOR3* pEye, // местоположение камеры в сценеD3DXVECTOR3* pAt, // точка, на которую направлена камераD3DXVECTOR3* pUp // вектор, задающий направление вверх - (0, 1, 0)

);

Параметр pEye задает точку пространства, в которой располагается камера. Параметр pAt задает ту точку сцены, на которую направлена камера. Параметр pUp - это вектор, который задает направление «вверх» для нашей сцены. Почти всегда это вектор, совпадающий с осью Y - (0, 1, 0).

D3DXMatrixPerspectiveFovLH, ADDR ProjectionMatrix, FieldOfView, AspectRatio, NearViewPlanZ, FarViewPlanZ

D3DXMatrixPerspectiveFovLH - создает матрицу проекции на основании описания усеченной пирамиды видимого пространства.

D3DXMATRIX *D3DXMatrixPerspectiveFovLH(DXMATRIX* pOut, // возвращает матрицу проекцииfovY, // вертикальный угол поля зрения в радианахAspect, // форматное соотношение = ширина / высотаzn, // расстояние до передней полскостиzf // расстояние до задней плоскости

);

Параметр форматного соотношения заслуживает дополнительных пояснений. Геометрия в окне проекции в конечном итоге преобразуется в экранное пространство. Перенос изображения из квадратной области (окна проекции) на экран, который, как известно, прямоугольный, приводит к возникновению искажений. Форматное соотношение, являющееся просто соотношением между сторонами экрана, используется для корректировки искажений возникающих при отображении квадрата на прямоугольник.

форматноеСоотношение = ширинаЭкрана / высотаЭкранаDXLoadMeshFromXA, addr Teapot, D3DXMESH_DYNAMIC,pd3dDevice, 0, 0, NULL, 0, addr TeapotP

D3DXLoadMeshFromXA - загружает в приложение X-Файл.

HRESULT D3DXLoadMeshFromX(        pFilename, Options,DDEVICE9 pDevice,DXBUFFER*  ppAdjacency,DXBUFFER*   ppMaterials,DXBUFFER*         ppEffeetInstances,*       pNumMaterials,

LPD3DXMESH* ppMesh

);

§  pFilename - указатель на строку, в которой приведено имя загружаемого Х-файла;

§  Options - член перечисляемого типа d3dxmesh, определяет комбинацию одного или более флагов для различных вариантов создания мэша. Рассмотрим несколько из имеющихся флагов:

o   d3dxmesh_vb_systemmem - этот флаг необходимо использовать с флагом D3DPOOL_SYSTEMMEM для определения класса памяти буфера вершин;

o   D3DXMESH_VB_MANAGED - применяется с флагом D3DPOOL_MANAGED для определения класса памяти буфера вершин;

o   D3DXMESH_IB_SYSTEMMEM - этот флаг необходимо использовать с флагом D3DPOOL_SYSTEMMEM для определения памяти индексного буфера;

o   D3DXMESH_IB_MANAGED - применяется с флагом D3DPOOL_MANAGED для определения памяти индексного буфера;

o   D3DXMESH_USEHWONLY - используется для обработки только аппаратных средств;

o   D3DXMESH_MANAGED - эквивалент комбинации двух флагов D3DXMESH_VB_MANAGED И D3DXMESH_IB_MANAGED;

o   D3DXMESH_SYSTEMMEM - Он эквивалентен комбинации двух флагов D3DXMESH_VB_SYSTEMMEM и D3DXMESH_IB_SYSTEMMEM;

§  pDevice - это указатель pDirect3DDevice на интерфейс IDirect3DDevice9, связывающий Х-файл с устройством Direct3D;

§  ppAdjacency - адрес указателя на буфер, содержащий данные о смежности. В этом параметре используется указатель на интерфейс ID3DXBuffer

§  ppMaterials - адрес указателя на интерфейс ID3DXBuffer. По возвращению функции этот параметр заполнится данными структуры D3DXMATERIAL для Х-файла;

§  ppEffeetInstances - адрес указателя на интерфейс ID3DXBuffer, содержащий специфические эффекты.

§  pNumMatегiа1s - указатель на массив данных для структуры D3DXMATERIAL.

§  ppMesh - адрес указателя на интерфейс ID3DXMesh, результат всей операции.dxmesh GetFVF,TeapotPGetFVF() - Возвращает значение типа DWORD, описывающее формат вершин сетки.dxmesh GetNumBytesPerVertex,TeapotPGetNumBytesPerVertex() - Возвращает количество байт, занимаемых описанием одной вершины.dxmesh GetNumVertices,TeapotPGetNumVertices() - Возвращает количество вершин в буфере вершин.dxmesh GetNumFaces,TeapotPGetNumFaces() - Возвращает количество граней (треугольных ячеек) в сетке.

d3dxmesh GetVertexBuffer,TeapotP, addr TeapotP_VBGetVertexBuffer(LPDIRECT3DVERTEXBUFFER9* ppVB); - Получает буфер вершин для данной сетки.dxmesh GetIndexBuffer,TeapotP, addr TeapotP_IBGetIndexBuffer(LPDIRECT3DINDEXBUFFER9* ppIB); - Получает буфер индексов для данной сетки.DXAssembleShaderFromFile, addr f_VS, 0, 0, D3DXSHADER_DEBUG, addr a_VS,0DXAssembleShaderFromFile - сборка шейдера из файлаD3DXAssembleShaderFromFile(    pSrcFile,D3DXMACR0* pDefines,DXINCLUDE plnclude,    Flags,DXBUFFER* ppShader,DXBUFFER* ppErrorMsgs

);

Функция D3DXAssembieShaderFromFile () имеет следующие параметры:

§  pSrcFile - имя зафужаемого файла, содержащего программу вершинного шейдера;

§  pDefines - указатель препроцессора;

§  pInciude ~ опциональный указатель интерфейса ID3DXInciude;

§  Flags - флаги, идентифицирующие шейдер;

§  ppShader - возвращает буфер, содержащий откомпилированный код шейдера. Здесь используется указатель Code на буфер LPD3DXBUFFER;

§  ppErrorMsgs - сообщение о возврате ошибок.

d3dev9 CreateVertexShader, pd3dDevice,b_VS ,addr c_VS- создает вершинный шейдер.CreateVertexShader(DWORD*   pFunction,DVertexShader9** ppShader

);

Функция CreateVertexShader () имеет следующие параметры:

§  рFunction - указатель, содержащий данные, возвращаемые функцией GetBufferPointer. Эта функция не имеет параметров и возвращает указатель на буфер данных.

§  ppShader - указатель на интерфейс IDirect3DVertexShader9.

d3dev9 SetVertexShaderConstantF,pd3dDevice,0, addr m_VS1 , 4 -занесение матрицы в необходимый константный регистр

HRESULT SetVertexShaderConstantF(   StartRegister,float* pConstantData,         Vector4fCount

);

Функция SetVertexShaderConstantFO имеет следующие параметры:

§  StartRegister - первый номер регистра, в который будут записаны данные;

§  pConstantData - указатель, содержащий данные для записи в регистр;

§  vector4fCount - количество необходимых регистров для размещения данных.