Создание игр » DirectX 9, Featured » Vertex buffer, Index buffer
Vertex buffer, Index buffer
Vertex buffer и Index buffer обычно используются для хранения информации о моделях в Direct3D. Соответственно, один из них хранит информацию о вершинах модели, а второй – об индексах, которые определяют из каких именно вертексов будут собираться треугольники модели. Vertex buffer, фактически, может хранить очень много данных – информацию о положении в мире, о нормалях, TBN-пространстве (используется в частности для normal mapping) и много другой информации. Учитывая, что хранить каждый тип информации в vertex buffer можно разными способами – они часто получаются достаточно сложными по формату и методам создания/упаковки данных в них. В то же время Index buffer обычно крайне прост – он просто хранит индексы (номера) вертексов и больше никакой дополнительной информации. Давайте же разберёмся поподробнее в том, зачем нам вообще использовать Vertex buffer’s и Index buffer’s.
Vertex Buffer
Вертексный буфер это буфер, хранящий данные о вертексах. Конкретнее, он может хранить:
- информацию о позициях (например, позиция vertex’а в мире)
- информацию о текстурных координатах в данном вертексе
- информацию о цвете
- информацию о нормалях к данном вертексу
- и многое другое
Конкретный список типов данных, которые можно хранить в vertex’е вертексного буфера, Вы можете посмотреть в
Index Buffer
Индексные буферы используются для задания индексов (номеров) вертексов в модели, из которых графическая карта будет “собирать” треугольники для отрисовки. На картинке справа Вы видите, как это задаётся. У нас есть 4 точки, составляющие квад, который, в свою очередь состоит из 2х треугольников. Из этих 4 точек, 2 штуки общие для обоих треугольников. Соответственно, в индексном буфере мы указываем индексы этих точек для использования как в первом, так и во втором треугольнике. Но что же нам это даёт? А вот что:
- Во-первых, мы экономим память на вертексах. Размер индекса либо 2 байта, либо 4, размер вертекса обычно не меньше 16-24 байт, а бывает и больше. Соответственно, в случае того же квада, если бы мы не использовали индексы, то vertex’ы занимали бы 6*24 = 144 байта. С индексами они займут 4*24 (вертексы) + 6*2 (индексы) = 96+12 = 118 байт. Т.е. мы сэкономим около 20% памяти. А для больших и хорошо оптимизированных моделей эта экономия может быть даже больше 50%.
- Во-вторых, только индексированные примитивы обрабатываются кэшем видео-карты. А кэш видео-карты позволяет не обрабатывать повторяющиеся вертексы (т.е. вертексы с одинаковыми индексами). Без использования индексов этого не просиходит. Таким образом, мы можем сэкономить ещё какой-то % производительности – обычно он не очень большой, но это вовсе не значит, что он совершенно не заметен: если у вас в кадре будет много “тяжёлых” моделей и в каждой много вертексов – разница может быть очень существенной.
Создание Vertex buffer и Index buffer
Поскольку и Vertex buffer, и Index buffer обычно хранятся непосредственно в памяти видео-карты, для их создания (выделения под них места) и работы с ними, в Direct3D есть отдельные функции:
HRESULT CreateVertexBuffer( [in] UINT Length, [in] DWORD Usage, [in] DWORD FVF, [in] D3DPOOL Pool, [out, retval] IDirect3DVertexBuffer9 **ppVertexBuffer, [in] HANDLE *pSharedHandle ); |
Эта функция позволяет создать новый vertex buffer, при этом указывается:
- длина создаваемого vertex buffer’а (в байтах!!!)
- как мы будем его использовать, обычно = D3DUSAGE_WRITEONLY
- формат вертексов в буфере, в последнее время чаще всего ставят =0
- Pool, в котором будет создан буфер, обычно это либо D3DPOOL_DEFAULT, либо D3DPOOL_MANAGED
- передаётся указатель на указатель (угу, именно так) на вертексный буфер. в этот указатель функция запишет адрес, по которому был создан буфер.
- последний параметр не используется и всегда ставится =0
HRESULT CreateIndexBuffer( [in] UINT Length, [in] DWORD Usage, [in] D3DFORMAT Format, [in] D3DPOOL Pool, [out, retval] IDirect3DIndexBuffer9 **ppIndexBuffer, [in] HANDLE *pSharedHandle ); |
Создание index buffer аналогично:
- Указываем длину буфера (в байтах)
- Как будем использовать – аналогично вертексному обычно = D3DUSAGE_WRITEONLY
- Форматов бывает всего два: D3DFMT_INDEX16 (16битный индекс, WORD), либо D3DFMT_INDEX32 (32битный индекс, DWORD)
- Указатель, по которому запишется адрес созданного буфера
- Ноль, не используется
Выводы
Выводы из всего этого очень просты: по возможности, всегда используйте index & vertex buffer’ы, т.к. это не только сократит количество памяти, используемой моделью, но и повысит быстродействие вашей программы. При этом, хочу заменить, что я лично использую их далеко не всегда – часто бывает ситуация, когда на экране надо нарисовать буквально 1-2 квада или треугольника, и в этом случае труд геморой с буферами совершенно не оправдывает себя – проще вызывать DPUP или DIPUP. В общем, оптимизация оптимизацией, но экономить на спичках не стоит – самый ценный ресурс, это ваше время, а вовсе не мощность видео-карты и/или компьютера. В конце-концов, ничего не мешает сделать отрисовку через DPUP/DIPUP, а если программа будет тормозить – тогда уже и оптимизировать.
Примеры использования описанных функций, а так же некоторых других, я дам в следующем уроке, когда мы будем применять полученные знания на практике.
Раздел: DirectX 9, Featured · Теги: Direct3D, DirectX, Оптимизация, Создание движка
Классно!
А как обстоят дела в больших и серъёзных проектах: там для каждой модели описывают класс, который содержит VertexBuffer и IndexBuffer? Наверное, забегаю вперёд поезда? Тогда ждём продолжения)
Antony, я очень постараюсь успеть уже сегодня дописать следующий урок и там всё объясню
Если же отвечать на ваш вопрос кратко, то да. Чаще всего просто описывается один класс, который содержит в себе указатели на Vertex Buffer и соответствующий Index Buffer. Далее просто создаются объекты этого класса, в конструктор (или в функцию-лоадер) этого класса передаётся имя файла с моделью и объект класса её загружает. Т.е. получается один класс, много моделей и каждый объект, хоть они и одного класса все, может содержать в себе собственную, уникальную 3д-модель.
Спасибо полезная информация!
Спасибо полезная информация!