Я работаю над своим собственным 3d-движком и задаю следующий вопрос:
У меня есть абстрактный объект, который обрабатывает геометрию (вершины и грани) . Он использует внутреннее хранилище для этой геометрии, позволяет редактировать, и у моего объекта рендерера есть метод RenderGeometry
.
С этим дизайном мой процесс рендеринга включает в себя шаг geometry caching
. Итак, у рендерера есть какой-то картоподобный контейнер
std::map<Geometry*, CachedGeometry*> map;
и здесь Geometry
обозначает мое собственное хранилище геометрии, а CachedGeometry
означает пару аппаратных индексов и буферов вершин, которые затем можно отобразить (в случае DirectX 9 это будут IDirect3D9VertexBuffer*
и IDirect3D9IndexBuffer*
.
И, ну, все выглядит отлично и очень удобно. Тем не менее, каждый вызов рендеринга Geometry*
требует огромных затрат времени - найти этот Geometry*
объект в моем внутреннем хранилище и только потом рендерить CachedGeometry*
.
.
В случае простых сцен эти накладные расходы были, конечно, минимальными, но когда я попытался визуализировать ландшафт с огромным количеством небольших пространственных объектов (пятен), профилирование показало, что около 20% затраченного времени в рендеринге фактически использовался для std::map
поисков.
Контейнеры на основе хэша (на самом деле boost::unordered_map
) показали еще худшую производительность (почему?) , и этот процент вырос до 35%.
Итак - чтобы подвести итог - что мне делать в этой ситуации? Полагаю, этот дизайн действительно удобен и "уместен" , но имеет снижение производительности абстракции.
Я думаю, что, вероятно, мне следует попробовать "более противный" подход и ввести в моем рендере методы, подобные StoreGeometry
, которые будут возвращать индекс объекта (например, int
), чтобы метод RenderGeometry
выглядел как RenderGeometry(int stored_geometry_index)
.
Хотя это выглядит очень плохо, возможно, это могло бы помочь мне сократить количество поисков.
Как вы думаете? Может быть, какой-то альтернативный подход? Что современные двигатели делают с предэкранированием геометрии?