|
3. Рисование в Direct3D
3.1. Подготовка к рисованию
Любая трехмерная сцена состоит из объектов. Объекты представляют собой сетки с треугольными ячейками. Точка, в которой сходятся
два ребра ячейки, называется вершиной. Таким образом, первое, что нужно сделать для задания геометрии - это создать структуру, описывающую
каждую вершину. Вот эта структура.
struct SimpleVertex
{
float x, y, z; //координаты
static const DWORD FVF;
};
Константа FVF (Flexible Vertex Format) описывает формат хранения вершин.
const DWORD SimpleVertex::FVF = D3DFVF_XYZ;//только координаты
Затем, для конструирования сцены нам понадобятся три матрицы: матрица мира, матрица проекции и матрица вида. Рассмотрим
назначение каждой из них.
Во многих случаях удобнее каждый объект сцены задавать относительно своей системы координат. Но, в последствии, их все-равно
нужно привести к единой (мировой) системе координат. За это отвечает матрица мира. Допустим, нам необходимо поместить некий объект в точку мирового
пространства с координатами (x, y, z). Для этого мы должны написать следующий код:
//создаем матрицу
D3DXMATRIX WorldMatrix;
//преобразуем её в матрицу перемещения
D3DXMatrixTranslation(&WorldMatrix, x, y, z);
//и задаем как мировую матрицу
pDevice->SetTransform(D3DTS_WORLD, &WorldMatrix);
Затем, нам нужно указать, как наша сцена будет проецироваться на экранную плоскость. Для этого используется матрица проекции.
//создаем матрицу
D3DXMATRIX ProjMatrix;
//заполняем её
D3DXMatrixPerspectiveFovLH(&ProjMatrix,
PI * 0.5f,//угол поля зрения
(float)width / (float)height,//ширина экрана / высота экрана
1.0,
1000.0f);
//задаем как матрицу проекции
рDevice->SetTransform(D3DTS_PROJECTION, &ProjMatrix);
И последнее, что нужно сделать для создания сцены - расположить в пространстве виртуальную камеру. Камера задается точкой
местоположения и тремя векторами-направлениями, ориентирующими её в пространстве.
//задаем соответствующие вектора
D3DXVECTOR3 position(5.0f, 3.0f, –10.0f);
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
//создаем матрицу
D3DXMATRIX V;
//инициализируем её
D3DXMatrixLookAtLH(&V, &position, &target, &up);
//и задаем как матрицу вида
pDevice->SetTransform(D3DTS_VIEW, &V);
3.2. Использование буферов вершин и индексов
Буферы вершин и индексов представляют собой непрерывные участки памяти. В буфере вершин хранится информация о каждой точке сцены. В буфере
индексов хранится информация о том, как эти точки соединяются. В коде программы, буферы вершин и индексов задаются интерфейсами
IDirect3DVertexBuffer9 и IDirect3DIndexBuffer9 соответственно. Рассмотрим функции создания буферов: HRESULT IDirect3DDevice9::CreateVertexBuffer()
- для вершин, HRESULT IDirect3DDevice9::CreateIndexBuffer() - для индексов. Так как эти функции различаются только одним параметром, то рассмотрим
их вместе.
HRESULT IDirect3DDevice9::CreateVertexBuffer(
UINT Length,
DWORD Usage,
DWORD FVF,
D3DPOOL Pool
IDirect3DVertexBuffer9** ppVertexBuffer,
HANDLE* pSharedHandle);
HRESULT IDirect3DDevice9::CreateIndexBuffer(
UINT Length,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DIndexBuffer9** ppIndexBuffer,
HANDLE* pSharedHandle);
Length - размер буфера в байтах.
Usage - параметр, указывающий особенности использования буфера.
FVF - настраиваемый формат вершин.
Pool - пул памяти, в который будет помещен буфер.
Format - формат индексов.
ppVertexBuffer (ppIndexBuffer) - адрес указателя на будер вершин (индексов).
pSharedHandle - всегда NULL.
Вот пример создания буфера вершин:
IDirect3DVertexBuffer9* vb;
pDevice->CreateVertexBuffer(
8 * sizeof(SimpleVertex),//8 вершин
0,
D3DFVF_XYZ,
D3DPOOL_MANAGED,
&vb,
0);
Для доступа к буферу необходимо получить указатель на область памяти, в которой находится буфер. Этот указатель получается
с помощью метода Lock();
SimpleVertex* vertices;
vb->Lock(0, 0, (void**)&vertices, 0);// заблокировать буфер
//пишем данные в буфер
vb->Unlock();// разблокировать буфер
3.3. Вывод на экран
Рассмотрим код процедуры, выводящей нашу сцену на экран:
void Draw(void)
{
//очистка экрана
pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f), 1.0f, 0);
//мировая матрица
D3DXMATRIX matWorld;
//приводим ее к единичной и задаем как мировую
D3DXMatrixIdentity(&matWorld);
pDevice->SetTransform(D3DTS_WORLD, &matWorld);
//начинаем визуализацию
pDevice->BeginScene();
//задаем буфер вершин
pDevice->SetStreamSource(0, vb, 0, sizeof(SimpleVertex));
//задаем буфер индексов
pDevice->SetIndices(ib);
//задаем формат вершин
pDevice->SetFVF(SimpleVertex::FVF);
//рисуем сцену
pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, 8, 0, 12);
//заканчивем визуализацию
pDevice->EndScene();
//производим блиттинг
pDevice->Present(NULL, NULL, NULL, NULL);
}
Отдельного рассмотрения заслуживает только метод IDirect3DDevice9::DrawIndexedPrimitive.
HRESULT IDirect3DDevice9::DrawIndexedPrimitive(
D3DPRIMITIVETYPE Type,
INT BaseVertexIndex,
UINT MinIndex,
UINT NumVertices,
UINT StartIndex,
UINT PrimitiveCount);
Type - тип выводимого примитива (точка, линия, треугольник).
BaseVertexIndex - смещение (в вершинах) относительно начального индекса первого объекта в потоке вывода.
MinIndex - минимальное значение индекса, которое будет использовано.
NumVertices - количество выводимых вершин.
StartIndex - индекс, с которого начинается вывод.
PrimitiveCount - количество выводимых примитивов.
Пример приложения: "Куб"
|
|