
Работа с интерфейсами
DirectXоснован на технологии COM (Component Object Model - Компонентная Модель Объектов) . Возможно, эта технология имеет ряд преимуществ и упрощает жизнь разработчику подобных продуктов, в данном случае тем, кто разрабатывал DirectX, однако для пользователей это означает дополнительное изучение порядка работы с такой моделью.
Основная идея COM заключается в работе с указателями на виртуальную таблицу функций. В терминологии DirectX вместо слова функция используется понятие интерфейс и методы. Приблизительная схема организации таких таблиц изображена на рисунке:
Из рисунка видно, что имеется указатель на таблицу интерфейсов, каждая ячейка которой в свою очередь содержит указатели на методы того или иного интерфейса в отдельности. Очевидно, что вызов нужного метода напрямую невозможен. Только произведя некоторые манипуляции с указателем, появляется возможность до него добраться. Порядок таких манипуляций можно описать следующими действиями:
1. Создать объект
2. Получить указатель на соответствующий интерфейс этого объекта.
3. Используя данный указатель вызвать нужный метод.
Создав один раз объект, и получив указатель на нужный интерфейс, можно сколь угодно вызывать необходимые методы.
Если в языке C++ данный механизм реализован в таком виде:
// Создали объект и получили указатель на интерфейс IDirect3D9
pd3d9 = Direct3DCreate9 (D3D_SDK_VERSION);
// Вызвали метод CreateDevice
pd3d9 -> CreateDevice (arg1, arg2, arg3, arg4, arg5, arg6, arg7);
То в ассемблере это будет выглядеть так:
invoke Direct3DCreate9, D3D_SDK_VERSION ; Создали объект
mov pd3d9, eax ; получили указатель
push arg7
push arg6
push arg5
push arg4
push arg3
push arg2
push arg1
push pd3d9
mov eax, pd3d9
mov eax, [eax]
call dword ptr [eax+3Ch]
Смысл команд, приведенных выше, сводится к занесению данных для метода CreateDevice в стек; получению указателя на таблицу методов, используя указатель на интерфейс; и вызов самого метода CreateDevice. При этом число 3Ch является просто-напросто порядковым номером CreateDevice в таблице указателей на методы, умноженным на четыре.
Подобные операции с вычислением истинного адреса метода способны отбить желание работать на ассемблере с COM моделью. Избежать этого можно используя макрос d3d9.
Программа, которая совершает то же самое, что и указанная выше, но уже с использованием такого макроса:
invoke Direct3DCreate9, D3D_SDK_VERSION ; Создали объект
mov pd3d9, eax ; получили указатель
d3d9 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 ,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
ADDR BackBufferWidth, ADDR pd3dDevice
Метод CreateDevice создает объект IDirect3DDevice9.
HRESULT IDirect3D9::CreateDevice(
UINT Adapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS *pPresentationParameters,
IDirect3DDevice9** 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, NULL
D3DXMatrixRotationY - Вращение по оси Y.
D3DXMATRIX* D3DXMatrixRotationY(
D3DXMATRIX *pOut,
FLOAT Angle
);
Параметры:
pOut — указатель на структуру D3DXMATRIX, в которую помешается исходный результат операции;
Angle — угол вращения в радианах по оси Y
D3DXMatrixRotationZ, ADDR WorldMatrix, RotZ
D3DXMatrixRotationZ- Вращение по осиZ.
D3DXMATRIX* D3DXMatrixRotationZ(
D3DXMATRIX *pOut,
FLOAT Angle
);
Параметры:
pOut — указатель на структуру D3DXMATRIX, в которую помешается исходный результат операции;
Angle — угол вращения в радианах по оси Z
D3DXMatrixLookAtLH, ADDR ViewMatrix, ADDR EyeVector, ADDR LookAtVector, ADDR UpVector
D3DXMatrixLookAtLH - вычислить матрицу преобразования вида.
D3DXMATRIX *D3DXMatrixLookAtLH(
D3DXMATRIX* pOut, // указатель на возвращаемую матрицу преобразования
CONST D3DXVECTOR3* pEye, // местоположение камеры в сцене
CONST D3DXVECTOR3* pAt, // точка, на которую направлена камера
CONST D3DXVECTOR3* pUp // вектор, задающий направление вверх – (0, 1, 0)
);
Параметр pEyeзадает точку пространства, в которой располагается камера. ПараметрpAtзадает ту точку сцены, на которую направлена камера. ПараметрpUp— это вектор, который задает направление «вверх» для нашей сцены. Почти всегда это вектор, совпадающий с осью Y — (0, 1, 0).
D3DXMatrixPerspectiveFovLH, ADDR ProjectionMatrix, FieldOfView, AspectRatio, NearViewPlanZ, FarViewPlanZ
D3DXMatrixPerspectiveFovLH - создает матрицу проекции на основании описания усеченной пирамиды видимого пространства.
D3DXMATRIX *D3DXMatrixPerspectiveFovLH(
D3DXMATRIX* pOut, // возвращает матрицу проекции
FLOAT fovY, // вертикальный угол поля зрения в радианах
FLOAT Aspect, // форматное соотношение = ширина / высота
FLOAT zn, // расстояние до передней полскости
FLOAT zf // расстояние до задней плоскости
);
Параметр форматного соотношения заслуживает дополнительных пояснений. Геометрия в окне проекции в конечном итоге преобразуется в экранное пространство. Перенос изображения из квадратной области (окна проекции) на экран, который, как известно, прямоугольный, приводит к возникновению искажений. Форматное соотношение, являющееся просто соотношением между сторонами экрана, используется для корректировки искажений возникающих при отображении квадрата на прямоугольник.
форматноеСоотношение = ширинаЭкрана / высотаЭкрана
D3DXLoadMeshFromXA, addr Teapot, D3DXMESH_DYNAMIC,pd3dDevice, 0, 0, NULL, 0, addr TeapotP
D3DXLoadMeshFromXA- загружает в приложение X-Файл.
HRESULT D3DXLoadMeshFromX(
LPCTSTR pFilename,
DWORD Options,
LPDIRECT3DDEVICE9 pDevice,
LPD3 DXBUFFER* ppAdjacency,
LPD3DXBUFFER* ppMaterials,
LPD3DXBUFFER* ppEffeetInstances,
DWORD* pNumMaterials,
LPD3DXMESH* ppMesh
);
pFilename — указатель на строку, в которой приведено имя загружаемого Х-файла;
Options — член перечисляемого типа d3dxmesh, определяет комбинацию одного или более флагов для различных вариантов создания мэша. Рассмотрим несколько из имеющихся флагов:
d3dxmesh_vb_systemmem— этот флаг необходимо использовать с флагом D3DPOOL_SYSTEMMEM для определения класса памяти буфера вершин;
D3DXMESH_VB_MANAGED — применяется с флагом D3DPOOL_MANAGED для определения класса памяти буфера вершин;
D3DXMESH_IB_SYSTEMMEM — этот флаг необходимо использовать с флагом D3DPOOL_SYSTEMMEM для определения памяти индексного буфера;
D3DXMESH_IB_MANAGED — применяется с флагом D3DPOOL_MANAGED для определения памяти индексного буфера;
D3DXMESH_USEHWONLY — используется для обработки только аппаратных средств;
D3DXMESH_MANAGED — эквивалент комбинации двух флагов D3DXMESH_VB_MANAGED И D3DXMESH_IB_MANAGED;
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, результат всей операции.
d3dxmesh GetFVF,TeapotP
DWORD GetFVF() — Возвращает значение типа DWORD, описывающее формат вершин сетки.
d3dxmesh GetNumBytesPerVertex,TeapotP
DWORD GetNumBytesPerVertex() — Возвращает количество байт, занимаемых описанием одной вершины.
d3dxmesh GetNumVertices,TeapotP
DWORD GetNumVertices() — Возвращает количество вершин в буфере вершин.
d3dxmesh GetNumFaces,TeapotP
DWORD GetNumFaces() — Возвращает количество граней (треугольных ячеек) в сетке.
d3dxmesh GetVertexBuffer,TeapotP, addr TeapotP_VB
HRESULT GetVertexBuffer(LPDIRECT3DVERTEXBUFFER9* ppVB); - Получает буфер вершин для данной сетки.
d3dxmesh GetIndexBuffer,TeapotP, addr TeapotP_IB
HRESULT GetIndexBuffer(LPDIRECT3DINDEXBUFFER9* ppIB); - Получает буфер индексов для данной сетки.
D3DXAssembleShaderFromFile, addr f_VS, 0, 0, D3DXSHADER_DEBUG, addr a_VS,0
D3DXAssembleShaderFromFile – сборка шейдера из файла
HRESULT D3DXAssembleShaderFromFile(
LPCTSTR pSrcFile,
CONST D3DXMACR0* pDefines,
LPD3DXINCLUDE plnclude,
DWORD Flags,
LPD3DXBUFFER* ppShader,
LPD3DXBUFFER* ppErrorMsgs
);
Функция D3DXAssembieShaderFromFile() имеет следующие параметры:
pSrcFile— имя зафужаемого файла, содержащего программу вершинного шейдера;
pDefines— указатель препроцессора;
pInciude~ опциональный указатель интерфейсаID3DXInciude;
Flags— флаги, идентифицирующие шейдер;
ppShader— возвращает буфер, содержащий откомпилированный код шейдера. Здесь используется указательCodeна буферLPD3DXBUFFER;
ppErrorMsgs— сообщение о возврате ошибок.
d3dev9 CreateVertexShader, pd3dDevice,b_VS ,addr c_VS
CreateVertexShader– создает вершинный шейдер.
HRESULT CreateVertexShader(
const DWORD* pFunction,
IDirect3DVertexShader9** ppShader
);
Функция CreateVertexShader () имеет следующие параметры:
рFunction— указатель, содержащий данные, возвращаемые функциейGetBufferPointer. Эта функция не имеет параметров и возвращает указатель на буфер данных.
ppShader — указатель на интерфейс IDirect3DVertexShader9.
d3dev9 SetVertexShaderConstantF,pd3dDevice,0, addr m_VS1 , 4
SetVertexShaderConstantF–занесение матрицы в необходимый константный регистр
HRESULT SetVertexShaderConstantF(
UINT StartRegister,
CONST float* pConstantData,
UINT Vector4fCount
);
Функция SetVertexShaderConstantFO имеет следующие параметры:
StartRegister — первый номер регистра, в который будут записаны данные;
pConstantData — указатель, содержащий данные для записи в регистр;
vector4fCount — количество необходимых регистров для размещения данных.
d3dev9 SetVertexShader,pd3dDevice,c_VS
SetVertexShader– устанавливает массив векторов.
HRESULT SetVertexShader(
D3DXHANDLE hParameter,
LPDIRECT3DVERTEXSHADER9 pVertexShader
);
Инициализирует идентифицируемый дескриптором hParameterобъект вершинного шейдера в файле эффекта на основании вершинного шейдера, на который указываетpVertexShader
d3dev9 SetPixelShader,pd3dDevice,c_PS
HRESULT SetPixelShader(
D3DXHANDLE hParameter,
LPDIRECT3DPIXELSHADER9 pPShader
);
Инициализирует идентифицируемый дескриптором hParameter объект пиксельного шейдера в файле эффекта на основании пиксельного шейдера, на который указывает pPShader
d3dev9 Clear, pd3dDevice, 0, NULL, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,Clearcolor, Zvalue, 0
Clear. – очищает различные буферы цветом
HRESULT Clear(
DWORD Count,
CONST D3DRECT* pRects,
DWORD Flags,
D3DCOLOR Color,
float Z,
DWORD Stencil
);
Функция clear о имеет следующие параметры:
Count — счетчик, указывает число прямоугольников, подвергающихся очистке. Вся область рендеринга состоит из массива прямоугольников. Если указать значение 0, то будет использована вся поверхность, т. е. весь массив прямоугольников или вся область рендеринга;
pRect — указатель на структуру D3DRECT, описывающей массив очищаемых прямоугольников.
Flags — параметр, определяющий флаги, указывающие, какие из поверхностей должны быть очищены. Этим параметром может быть любая комбинация из следующих флагов:
D3DCLEAR_STENCIL — очистит буфер трафарета до значения в параметре Stencil;
D3DCLEAR_TARGET — очистит буфер поверхности до цвета в параметре color. Воспользуемся данным флагом для очистки буфера поверхности в заданный цвет;
D3DCLEAR_ZBUFFER — очистит буфер глубины до значения в параметре z;
Сolor — цвет;
z — этот параметр задает значения для Z-буфера. Значение может находится в диапазоне от 0.0 — это самое близкое расстояние для средства просмотра и 1.0 — дальнее расстояние.
Stencil — значение буфера трафарета, может быть в диапазоне от 0 до 2n-1гдеnразрядная глубина буфера трафарета.
d3dev9 SetStreamSource, pd3dDevice, 0 , TeapotP_VB, 0, TeapotPB
SetStreamSource- Связывает буфер вершин с потоком данных.
HRESULT SetStrearSourse (
UINT StreamNumber,
IDlrect3DVertexBuffer* pStreamData,
UINT OffsetInBytes,
UINT Stride)
Параметры:
StreamNumber— определяет поток данных в диапазоне от 0 до -I,
pStrearxData — это указатель на интерфейс IDirect3DvertexBuffer, созданный для представления буфера вершин, который связывается с определенным потоком данных;
OffsetInBytes— смешение от начата потока до начала данных вершин. Измеряется в байтах. Здесь вы указываете, с какой вершины наминается вывод. Если поставить 0. то вывод будет происходить от первой вершины;
Stride — это своего рода "шаг в байтах", от одной вершины до другой
d3dev9 Present, pd3dDevice, NULL, NULL, NULL, NULL
Present- Предстаазяет содержимое буфера на дисплей.
HRESULT Present(
CONST RECT* pSourceRect,
CCIJST RECT* pDestRect,
HKND hDestWindowOverride,
CONST RGNCDATA* pDirtyRegion
);
Параметры:
pSourceRect— указатель на структуруRECTисходной поверхности. Если использовать значение null, то будет представлена полная исходная поверхность;
pDestRect— указатель на структуру RECT поверхности адресата;
hDestWindowOverride— указатель на окно адресата, чья клиентская область взята как адрес для этого параметра представления Установив значение null, мы тем самым говорим, что используем поле
hWndDeviceWindow в структуре D3DPRESENT_PARAMETERS;
pDirtyReqion — последний параметр, "отголосок" прежних версий DirectX и уже не используется. Оставлен просто для совместимости, по-этому устанавливается всегда в значение null.
d3dev9 DrawIndexedPrimitive, pd3dDevice, D3DPT_TRIANGLELIST, 0, 0, TeapotP_NV, 0, TeapotP_NF
DrawIndexedPrimitive– нарисовать примитив из индексного буфера.
HRESULT DrawIndexedPrimitive(
D3DPRIMITIVETYPE Type,
INT BaseVertexIndex,
UINT MinIndex,
UINT NumVertices,
UINT StartIndex,
UINT PrimitiveCount
);
Параметры:
Type— Тип рисуемого примитива.
BaseVertexIndex— Базисная величина, которая будет прибавлена к используемым в данном вызове индексам.
MinIndex— Минимальное значение индекса, которое будет использовано.
NumVertices— Количество вершин, которые будут обработаны данным вызовом.
StartIndex— Номер элемента буфера индексов, который будет отмечен как стартовая точка с которой начнется чтение индексов.
PrimitiveCount— Количество рисуемых примитивов.