Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2004.01.13;
Скачать: [xml.tar.bz2];

Вниз

Конструкция ресурсного мэнеджера в 3Д-игре   Найти похожие ветки 

 
NailMan   (2003-06-21 12:25) [0]

Хочу поделиться с секретами и посоветоваться насчет модификаций сабжа.

Вот как я устроил ресурсный мэнеджер:

Текстуры
В свою очередь текстуры хранятся в одном скомпилированном файле ресурса(со стандартной структурой расположения таблицы в конце файла).

Модели
Вся геометрия и материалы(свои включая директовский) хранятся в едином файле. Каждая модель может иметь [1..4] уровней LOD. Также в модели хранятся базовый индентификатор(своего рода GUID), массив коллизионных сфер(радиус и XYZ), и еще немножко всякой ботвы не очень существенного содержания.

Модели загружаются загрузчиком в специальный массив шаблонных объектов.
Геометрия загружается в 4 статических буфера(сейчас пока юзается первый), которые представляют из себя набор vertexbuffer, indexbuffer, freeindex.

Статический буфер
Идея статического буфера:
- все объекты(не модели, а конечные объекты) отсортированы по номеру используемого статического буфера
- при отрисовке кадра вызываю рендер объекта, скажем находящегося в первом стат.буфере. Он переключает его в Д3Ддевайсе(setStreamSource, setvertexshader, setindicies), и рендерит себя.
- следующий объект, находящийся в том же стат.буфере уже не будет устанавливать его(при установки стат.буфера сохраняется его номер в переменную CurrentPVB) сравнив требуемый номер СБ с текущим установленным. Таким образом избегаем лишних переключений VB/IB буферов, что очень экономит время(операция переключения буферов считается "тяжелой").
- Если следующий объект находится во втором стат.буфере, то вся история повторится.

Идея очень мне съэкономила время рендера, таким образом разница в ФПСах при юзании СБ и ID3DXMesh(с индивидуальным набором VB/IB и соответственно он всегда устанавливается при вызове DrawSubset) составила ~70 ФПС. 170(СБ) и 100(ID3DXMesh).

реализация:
- создается фиксированный набор VB/IB максимальной величины(65530 индексов)
- набор загружается в локальную память видеоадаптера
- данные в статическом буфере выровнены по макс. величине из vertexcount и index count, чтобы предотвратить фрагментацию, т.е. чтобы геометрия модели всегда была в одном наборе(стат. буфере).
тоесть примерно графически это выглядит так:

модель 0 модель 1 модель 2 моедель N
|vvvvvvvvvv |vvvvvvvvvvvvvvvv|vvvvvvvv |
|iiiiiiiiiiiiiiiii|iiiiiiiiiii |iiiiiiiiiiiiiii|
0 500 3000 ( vCount, fcount, junkcount-число кусков, а фактически число материалов) Хочу поделиться с секретами и посоветоваться насчет модификаций сабжа.

Вот как я устроил ресурсный мэнеджер:

Текстуры
В свою очередь текстуры хранятся в одном скомпилированном файле ресурса(со стандартной структурой расположения таблицы в конце файла).

Модели
Вся геометрия и материалы(свои включая директовский) хранятся в едином файле. Каждая модель может иметь [1..4] уровней LOD. Также в модели хранятся базовый индентификатор(своего рода GUID), массив коллизионных сфер(радиус и XYZ), и еще немножко всякой ботвы не очень существенного содержания.

Модели загружаются загрузчиком в специальный массив шаблонных объектов.
Геометрия загружается в 4 статических буфера(сейчас пока юзается первый), которые представляют из себя набор vertexbuffer, indexbuffer, freeindex.

Статический буфер
Идея статического буфера:
- все объекты(не модели, а конечные объекты) отсортированы по номеру используемого статического буфера
- при отрисовке кадра вызываю рендер объекта, скажем находящегося в первом стат.буфере. Он переключает его в Д3Ддевайсе(setStreamSource, setvertexshader, setindicies), и рендерит себя.
- следующий объект, находящийся в том же стат.буфере уже не будет устанавливать его(при установки стат.буфера сохраняется его номер в переменную CurrentPVB) сравнив требуемый номер СБ с текущим установленным. Таким образом избегаем лишних переключений VB/IB буферов, что очень экономит время(операция переключения буферов считается "тяжелой").
- Если следующий объект находится во втором стат.буфере, то вся история повторится.

Идея очень мне съэкономила время рендера, таким образом разница в ФПСах при юзании СБ и ID3DXMesh(с индивидуальным набором VB/IB и соответственно он всегда устанавливается при вызове DrawSubset) составила ~70 ФПС. 170(СБ) и 100(ID3DXMesh).

реализация:
- создается фиксированный набор VB/IB максимальной величины(65530 индексов)
- набор загружается в локальную память видеоадаптера
- данные в статическом буфере выровнены по макс. величине из vertexcount и index count, чтобы предотвратить фрагментацию, т.е. чтобы геометрия модели всегда была в одном наборе(стат. буфере).
тоесть примерно графически это выглядит так:

модель 0 модель 1 модель 2 моедель N
|vvvvvvvvvv |vvvvvvvvvvvvvvvv|vvvvvvvv |
|iiiiiiiiiiiiiiiii|iiiiiiiiiii |iiiiiiiiiiiiiii|
0 500 3000 400000

Идея загрузки геометрии в статический буфер:
- считываем параметры геометрии из модели(vCount, fcount, junkcount-число кусков, а фактически число материалов)
- РМ возвращает свободный буфер, который выбирается по максимальному значению из vcount и 3*facecount. Если в первый не влезает, то смотрим во следующем, если он не создан создаем его и возвращаем его номер и свободный индекс(0), если есть место то возвращаем его номер и свободный индекс(>0) и т.д.
- открываем vb и заливаем считанный массив вершин из файла модели. Закрываем.
- открываем ib, считываем индексы из файла и заливаем в ib прибавляя к каждому индексу FreeIndex(свободный индекс в СБ). закрываем.
- считываем таблицу аттрибутов и тоже изменяем StartVertex=StartVertex+freeindex и StartFace=StartFace*3+ freeindex(теперь startface стал начальным индексом, а не фейсом)

Объекты
При создании игрового объекта(генератором или из файла), проверяю есть ли в массиве шаблонных моделей, модель с GUIDом объекта. Если найдена, возвращаю его номер в буфере моделей.

При рендере объекта я использую собственную процедуру DrawSubset, в которую передаю номер модели в буфере моделей, и номер куска. Процедура устанавливает нужный СБ(номер которого берется из нужной модели) или игнорирует(если уже он установлен) и draw`ает его.

Модели загружаются перед загрузкой сцены(у меня это происходит при вылете с базы) и никогда не убиваются. Если на сцене появляется объект, модель которого незагружена, то модель грузится в он-лайне(понятно что будет маленький лаг) и объект создается. Предзагружаются наиболее часто встречающиеся модели на данном типе местности(завездном кластере).

Вот собсно мой сабж.

Если ли у кого предложения по модификации или более конструктивные решения по улучшению использования VB/IB?
В принципе ~20-30% места не используется, так же как и в кластерах винта при небольших файлах и большом размере кластера. Может есть более оптимальные варианты расположения?
Главное сохранить условия единственной установки пары VB/IB перед рендером блока моделей с однаковым номером буфера. Устанавливать IB для каждой модели неприменимо, так как теряется смысл статических буферов.


 
NailMan   (2003-06-21 12:28) [1]

Блин сместиось на русунке
Вот более правильный(надеюсь не сместится)

модель 0 модель 1 модель 2 модель N
vb|vvvvvvvvvv |vvvvvvvvvvvvvvvv|vvvvvvvv |
ib|ddddddddddddddddd|ddddddddddd |ddddddddddddddd|
0 500 3000 400000


 
NailMan   (2003-06-21 12:29) [2]

Вобщем вертикальные черточки на одинаковой позиции. :-)


 
Sapersky_   (2003-06-23 11:38) [3]

А флаг D3DXMESHOPT_SHAREVB в ID3DXMesh::Optimize не то же ли самое делает? Вряд ли имеются в виду буферы для разных субмешей - всё-таки это было бы извращением даже для Мелкософта (хранить субмеши в разных буферах). Или здесь объединяются только VB (но не IB), и толку от этого никакого? Надо бы протестировать...
А так вообще идея совершенно правильная. Относительно остающегося пустого места - так ведь необязательно задавать размер буфера именно 65530, можно и "утрамбовать" всю информацию в нём (заранее рассчитав, какой нужен размер). Другое дело, что, возможно, сам D3D "округлит" размер буферов так, что получится в результате то же самое...
Относительно вывода - ну, группировка по статическим буферам, чтобы меньше переключать - само собой... Далее, если, допустим, на одном кораблике несколько текстур (конечно, такие модели использовать нежелательно, но если других нет), т.е. он состоит из нескольких субмешей, и рисуется одновременно несколько одинаковых корабликов - можно попробовать сгруппировать вывод по текстурам, т.е. сначала рисуется первый субмеш для всех корабликов, потом второй и т.д. Меньше переключений текстур будет, но больше - матриц трансформации. Так что неизвестно ещё, что быстрее. Опять проверять надо.
Ещё - в космосиме можно попробовать т.н. impostors, т.е. вывод "спрайтами", полученными из моделей (модель рендерится в текстуру; перерисовка делается только при определённом изменении положения и ориентации корабля, т.е. не на каждом кадре). Спецэффекты можно делать (motion blur) - по этому поводу была статья "Four Tricks for Fast Blurring in Software and Hardware" by Alex Evans на Гамасутре. Хотя и здесь не всё однозначно - возможно, с HWTnL-ускорителем быстрее нарисовать модель, чем переключать вывод на текстуру.


 
NailMan   (2003-06-23 17:48) [4]

Или здесь объединяются только VB (но не IB), и толку от этого никакого? Надо бы протестировать...

В том то и фокус у меня был что установка IB для каждого вызова отрисовки практически не сильно увеличивал скорость, по сравнению с Id3dxmesh. Вот когда и VB и IB были общими для всех и устанавливались одновременно, т.е. индексы в IB были изменены с локальных на глобальные(+FreeIndex), все стало значительно быстрей.

А так вообще идея совершенно правильная. Относительно остающегося пустого места - так ведь необязательно задавать размер буфера именно 65530, можно и "утрамбовать" всю информацию в нём (заранее рассчитав, какой нужен размер).

Это также я рассматривал, но отверг так как модельки могут динамически подгружаться, а в этом случае потребуется пересоздавать буфер. А создание буферов - эт самые "тяжелые"
опрерации. Типа лучше создать максимального размера и не париться.

Другое дело, что, возможно, сам D3D "округлит" размер буферов так, что получится в результате то же самое...
хм...с текстурами он такой финт делает, а вот с буферами сомнительно. Хотя хрен знает, директ возвращает всегда остаток текстурной памяти кратной мегабайту. Видимо он все-таки буферы "округляет".

Ещё - в космосиме можно попробовать т.н. impostors, т.е. вывод "спрайтами", полученными из моделей (модель рендерится в текстуру; перерисовка делается только при определённом изменении положения и ориентации корабля, т.е. не на каждом кадре).

Это типа как в досовых wing commander-ах? 3Д спрйты вроде называются. :-))
Забавный способ. Я вобщето для каждой модельки по 4 LODa сделал. Сомневаюсь что в кадре одновременно в нулевом лоде будет даже 2 модельки, поэтому в основном модельки будут рендериться 2 и иногда 3-лода(простой куб).


 
Sapersky_   (2003-06-27 15:24) [5]

Ещё - в космосиме можно попробовать т.н. impostors, т.е. вывод "спрайтами", полученными из моделей (модель рендерится в текстуру; перерисовка делается только при определённом изменении положения и ориентации корабля, т.е. не на каждом кадре).

Это типа как в досовых wing commander-ах? 3Д спрайты вроде называются. :-))


Нет, это как в последнем NFS на минимальном уровне детализации или Flanker2 (да и во всех авиасимуляторах скорее всего). Качество при этом вовсе не обязательно должно страдать (хотя в NFS страдает - освещение отсутствует, и в результате машина выглядит совершенно плоской). Спрайты-то получаем из тех же моделей, хотя можно и заранее нарисовать. К тому же предполагается, что таким образом выводятся удалённые объекты, по которым уже не разберёшь, из чего они сделаны.

Сомневаюсь что в кадре одновременно в нулевом лоде будет даже 2 модельки, поэтому в основном модельки будут рендериться 2 и иногда 3-лода(простой куб).

Ну да, этот способ имеет наибольшую эффективность при наличии "массовок", в стратегиях вроде Homeworld (хотя не знаю, использовался ли он там). Имеются, правда, некоторые проблемы - в основном с Z-буфером... для спрайтов он неприменим, понятное дело, нужно сортировать, причём вообще все объекты.

Посмотрел медиаплеер... Довольно симпатично.
Имеется одна идея... Сам уж вряд ли соберусь писать, так что поделюсь.
Меня всегда раздражала неточность позиционирования при просмотре видео. У тебя с этим неплохо, можно передвигать вперёд-назад на 5 или сколько там секунд, но всё равно не очень удобно при поиске "вот того самого" кадра. Удобнее было бы что-то вроде thumbnails в программах-вьюерах. То есть генерируется несколько уменьшенных кадров с определённым интервалом и выводится в отдельном окне. Можно ещё оформить это под киноплёнку (нарисовать "перфорацию") - выглядеть должно очень эффектно. Опять же, найти нужное место достаточно легко. Хотя тормозить это дело, наверное, будет сильно. Но обновлять в реальном времени эти картинки и необязательно - можно при нажатии на "паузу", например. В общем, надо пробовать и смотреть, что получится.
Хотя может быть я и преувеличиваю значимость проблемы (позиционирования) - в основном кино смотрят всё-таки последовательно, а не по кадрам.
В плане уменьшения размеров EXE-шника - см. KOL. Каких-то особенных компонентов вроде не используется, так что вполне реально переписать. DirectX с KOL"ом работает, проверял (правда, проверял 7-й DX).



Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2004.01.13;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.009 c
1-37610
sergey 101
2003-12-28 13:26
2004.01.13
dll (строковый массив)


1-37734
raidan
2003-12-29 22:25
2004.01.13
Как в listbox узнать номер последней выделенной строки?


3-37499
Vint
2003-12-17 11:47
2004.01.13
ALTER TABLE


1-37702
sadretro
2003-12-25 23:02
2004.01.13
Как спрятать окно рабочей проги?


14-37910
_Mikhail
2003-12-21 13:01
2004.01.13
Вопрос по dll





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский