netlib.narod.ru< Назад | Оглавление | Далее >

3.1. Буферы вершин и индексов

Буферы вершин и индексов обладают сходными интерфейсами и предоставляют одинаковые методы, так что мы будем их рассматривать вместе. Буфер вершин представляет собой непрерывный участок памяти в котором хранятся данные вершин. Аналогичным образом, буфер индексов — это непрерывный участок памяти в котором хранятся данные индексов. Мы используем буферы вершин и индексов для хранения данных из соответствующих массивов по той причине, что эти буферы могут располагаться в памяти видеокарты. Визуализация данных, находящихся в памяти видеокарты, выполняется гораздо быстрее, чем визуализация данных, расположенных в системной памяти.

В коде буфер вершин представляется интерфейсом IDirect3DVertexBuffer9, а буфер индексов представляется интерфейсом IDirect3DIndexBuffer9.

3.1.1. Создание буферов вершин и индексов

Для создания буферов вершин и индексов используются следующие два метода:

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
);

У обоих методов большая часть параметров идентична, так что рассмотрим параметры обоих методов вместе:

 

ПРИМЕЧАНИЕ
Буфер, созданный без указания флага D3DUSAGE_DYNAMIC называется статическим буфером. Обычно статический буфер располагается в видеопамяти, где его содержимое может обрабатываться более эффективно. Однако, если вы сделаете буфер статическим, придется расплачиваться исключительно низкой скоростью записи в буфер и чтения из него. Поэтому мы будем использовать статические буферы для хранения статических данных (данных, которые не надо часто изменять). Хорошими кандидатами на размещение в статическом буфере являются ландшафты и здания, поскольку их геометрия обычно не изменяется во время работы приложения. Данные геометрии должны заноситься в статические буферы во время инициализации приложения, а не во время его работы.

 

ПРИМЕЧАНИЕ
Буфер, созданный с указанием флага D3DUSAGE_DYNAMIC называется динамическим буфером. Динамические буферы обычно располагаются в памяти AGP, где их содержимое может достаточно быстро обновляться. Видеокарта работает с динамическими буферами медленнее, чем со статическими, потому что данные перед визуализацией должны быть переданы из буфера в видеопамять. Главное преимущество динамических буферов — возможность быстрого обновления (быстрая запись данных центральным процессором). Следовательно, если вам надо часто изменять содержимое буфера, сделайте его динамическим. Хорошим кандидатом на размещение в динамическом буфере являются системы частиц, поскольку они анимируются и их геометрия обычно изменяется в каждом кадре.

 

ПРИМЕЧАНИЕ
Чтение данных из видеопамяти или из памяти AGP выполняется очень медленно. Следовательно, если вам во время работы приложения надо читать данные геометрии, лучше всего создать копию данных в системной памяти и обращаться для чтения к ней.

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

IDirect3DVertexBuffer9* vb;
_device->CreateVertexBuffer(
               8 * sizeof(Vertex),
               0,
               D3DFVF_XYZ,
               D3DPOOL_MANAGED,
               &vb,
               0);

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

IDirect3DIndexBuffer9* ib;
_device->CreateIndexBuffer(
               36 * sizeof(WORD),
               D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
               D3DFMT_INDEX16,
               D3DPOOL_MANAGED,
               &ib,
               0);

3.1.2. Доступ к памяти буфера

Для доступа к памяти буфера вершин или индексов нам необходимо получить указатель на область памяти с содержимым буфера. Мы получаем указатель на содержимое с помощью метода Lock. Не забудьте после завершения работы с буфером разблокировать его. Получив указатель на область памяти, можно считывать и записывать информацию.

ПРИМЕЧАНИЕ
Если при создании буфера вершин или индексов был указан флаг D3DUSAGE_WRITEONLY, вы не сможете читать информацию из этого буфера. Попытка выполнить чтение приведет к возникновению ошибки.

HRESULT IDirect3DVertexBuffer9::Lock(
        UINT OffsetToLock,
        UINT SizeToLock,
        BYTE** ppbData,
        DWORD Flags
);
HRESULT IDirect3DIndexBuffer9::Lock(
        UINT OffsetToLock,
        UINT SizeToLock,
        BYTE** ppbData,
        DWORD Flags
);

Рис. 3.1. Параметры OffsetToLock и SizeToLock

Рис. 3.1. Параметры OffsetToLock и SizeToLock определяют блокируемую область памяти. Если обоим параметрам присвоить нулевые значения, будет заблокирован весь буфер


Параметры у обоих методов одинаковы.

Флаги D3DLOCK_DISCARD и D3DLOCK_NOOVERWRITE опираются на тот факт, что в момент вызова функции блокировки часть памяти буфера может использоваться для визуализации. Если обстоятельства позволяют указывать эти флаги, то благодаря их использованию можно избежать простоев визуализации, которые могли бы произойти в ином случае.

Приведенный ниже пример демонстрирует обычный вариант использования метода Lock. Обратите внимание, что закончив работу мы сразу вызываем метод Unlock.

Vertex* vertices;
_vb->Lock(0, 0, (void**)&vertices, 0);    // заблокировать весь буфер

vertices[0] = Vertex(-1.0f, 0.0f, 2.0f);  // записать данные вершин
vertices[1] = Vertex( 0.0f, 1.0f, 2.0f);  // в буфер
vertices[2] = Vertex( 1.0f, 0.0f, 2.0f);

_vb->Unlock();                            // разблокировать буфер, когда
                                          // мы закончили работать с ним

3.1.3. Получение информации о буфере

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

D3DVERTEXBUFFER_DESC vbDescription;
_vertexBuffer->GetDesc(&vbDescription); // получаем информацию о буфере вершин

D3DINDEXBUFFER_DESC ibDescription;
_indexBuffer->GetDesc(&ibDescription); // получаем информацию о буфере индексов

Объявление структур D3DVERTEXBUFFER_DESC и D3DINDEXBUFFER_DESC выглядит следующим образом:

typedef struct _D3DVERTEXBUFFER_DESC {
     D3DFORMAT Format;
     D3DRESOURCETYPE Type;
     DWORD Usage;
     D3DPOOL Pool;
     UINT Size;
     DWORD FVF;
} D3DVERTEXBUFFER_DESC;

typedef struct _D3DINDEXBUFFER_DESC {
     D3DFORMAT Format;
     D3DRESOURCETYPE Type;
     DWORD Usage;
     D3DPOOL Pool;
     UINT Size;
} D3DINDEXBUFFER_DESC;

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz