Таки пришлось писать этот материал… Распалятся много не буду, представленный ниже исходник показывает как можно программно манипулировать данными мешбуферов загруженных 3д моделей. в этой работе я загрузил модель склонировал ее вершины(мешбуфер) 32*32 раза в и поместил в один единственный мешбуфер хранилище, а потом удалил из хранилища вершины клонов которые находятся на диагонали сгенерированного квадрата.  Для осуществления манипуляций мной написан класс дубликатор для конкретной модели. Порядок работы таков

1. Создаем экземпляр класса и передаем ему драйвер, менеджер сцены и пути к модели и ее текстуре
C_Dublicator(
irr::video::IVideoDriver *drv,
irr::scene::ISceneManager* mgr,
const irr::io::path& t_name,
const irr::io::path& m_name
)
в классе создается буфер хранилище (mb_storage), в который мы будем складывать копии буферов 3д модели

2. С помощью его метода duplicateTo(x,y) делаем копию буфера модели (cloneMeshBuffer) и позиционируем ее в указанные координаты и помещаем в буфер хранилище (appendBuffer), запоминаем смещение клона в хранилище (v_shifts,i_shifts)

3. C помощью duplicateDel(x,y) перебираем все смещения клонов(v_shifts) в хранилище и сверяем запрошенные координаты, таким образом определяем смещение клона в хранилище, по полученному смещению удаляем клон (removeBuffer)

вот следующим кодом я нарисовал «диагональ» :)

C_Dublicator dublicator(driver, smgr, «res/cube.jpg», «res/cube.3ds»);
for(int _x = 0; _x<32; _x++)
for(int _z = 0; _z<32; _z++)
dublicator.dublicateTo(_x,_z);

int z = 0;
for(int _x = 0; _x<32; _x++)
dublicator.dublicateDel(_x,z++);

а вот как это выглядит

test1

ну и самое главное – без чего ваша радость была бы не полной – исходник

irr_test1

Искренне Ваш, Эльмиго

P.s. сие творение работает только с моделями вершины которых умещаются в одном мешбуфере, для более объемных требуется усовершенствование, относительно не сложное.

P.s.s. Самое главное, о чем забыл сказать, так это для чего же по настоящему может понадобится вот эта куча кода в геймдеве на ирлихте.

Как уже я как-то говорил, ирлихт загружает вершины модели в мешбуферы разбивая по 65536 вершин на один буффер меша. Это не прихоть разработчиков, а вполне логичный поступок. Дело в том что как раз обмен с конвейером видеокарты идет как раз по 64к вершин, поэтому когда дело доходит до рендеринга, то просто перебрасываются последовательно куски памяти(мешбуферы), вместо хитрых циклов, которые бы отсчитывали эти 64к, если бы буфер был один.

Так вот типичный случай: ваша сцена содержит много-много статичных копий одной модели дерева(Дуба) с количеством данных 1кб, например 4096 дубов,  и вы совершенно естественны образом пихаете на сцену 4096 нод к которым прикрепляете эту модель и с ужасом для себя наблюдаете что ФПС колеблется в критическо-низкой позиции, чето порядка 30фпс. В чем дело?

Дело в том что при рендеринге сцены, помимо того что перебирается 4096 нод, которые препарируют прикрепленный меш, которые в свою очередь посылает на рендер свои буфера, т.е. 4096 раз на конвейер карты посылается 1к данных, хотя он может принять 64к… понимаете к чему клоню? Правильно конвейер жутко «голодает», вместо того чтобы «пить» глотками, вы его «поите» с пипетки.

А теперь совершенно естественно выплывает желание создать один единственный меш, утромбовать в его буфера все дубы (получится что вместо 4096 буферов у нас будет 4096/64=64)  и привязать этот меш к единственной же ноде и благоговеть от 1000фпс, а потом включаете VBO и просто экстазируете от 2000фпс даже на 10000  дубов :)

И… и в этом нам поможет часть методов описанных в этой статье!

Теперь все!

Ваш Эльмиго.

UPDATE: В исходнике в функции removeBuffer() в строке mb_storage->Indices[i] -= i_quant; заменено i_quant на v_quant.

Комментарий от Smeler (hard-station.ru): Вместо i_quant необходимо поставить v_quant, ведь мы индексируем вершины, а не индексы. Самое опасное, что ошибка в этом алгоритме в больших дублируемы моделях с числом вершин определённой кратности вызывает не полный «расколбас», а частичный, что даёт порчу секторов памяти и глючность всех программ, которые загружены в незащищённые сектора оперативной памяти, в первую очередь самой себя, что вызывает комментарии типо «иррлихт – глючная хрень».


Отзывов: 3 на “IrrLicht: низкоуровневое управление мешбуферами”

  1. Костя ()

    А если, например, эти дубы раскиданы по всей сцене и получается, что видеокарте будут предаваться все дубы, даже те, которые заведомо не будут виды (например находящиеся за камерой).

    Ведь автоматическое отсечение работает для ноды в целом, а если все дубы одна нода, то и рисоваться будут все в независимости от видимости.

    Или эффект от ускорения переброски данных в видокарту компенсирует лишние затраты видеокарты по расчету невидимых дубов?

  2. Костя ()

    И еще вопрос на счет VBO.
    Оно само должно включаться, если видеокарта его поддерживает? Или что-то надо написать в коде?

    И я так понял, VBO работает только для OpenGL, а для DirectX есть что-то подобное?

  3. Эльмиго ()

    да, Костя, именно так, хочешь не хочешь а перебрасывается все равно 64кб данных за раз, так что заполнение буфера под «пробку» даст только положительный эффект.

    VBO есть и для GL и для DX
    включается в обоих случаях
    irr::scene::IMeshSceneNode->getMesh()->setHardwareMappingHint(irr::scene::EHM_STATIC);

    пример здесь http://www.elmigo.ru/content/331


Оставьте свой отзыв

Вы должны войти, чтобы оставлять комментарии.