Фон:
Я проектирую простую систему трехмерного рендеринга для архитектуры типов систем сущностей с использованием C ++ и OpenGL. Система состоит из рендера и графа сцены. Когда я закончу первую итерацию рендера, я смогу распределить граф сцены в архитектуру ECS. На данный момент это так или иначе заполнитель. Если возможно, мои цели для рендера:
- Простота . Это для исследовательского проекта, и я хочу иметь возможность легко изменять и расширять мои системы (отсюда и подход ECS).
- Производительность . В моей сцене может быть много маленьких моделей, а также большие объемы с большой геометрией. Недопустимо получать объекты из контекста OGL и геометрии буфера каждый кадр рендеринга. Я стремлюсь к локальности данных, чтобы избежать промахов кэша.
- Гибкость . Он должен уметь отображать спрайты, модели и объемы (вокселы).
- Отделен . Граф сцены может быть преобразован в основную архитектуру ECS после того, как я напишу свой рендер.
- Modular . Было бы неплохо иметь возможность поменять местами разные рендеры без изменения графика сцены.
- Ссылочная прозрачность , означающая, что в любой момент времени я могу назначить ей любую действительную сцену, и она всегда будет отображать одно и то же изображение для этой сцены. В частности, эта цель не является обязательной. Я подумал, что это поможет упростить сериализацию сцен (мне нужно будет уметь сохранять и загружать сцены) и дать мне возможность переключаться между различными сценами во время выполнения для целей тестирования / экспериментов.
Проблема и идеи:
Я предложил несколько разных подходов, чтобы попробовать, но я борюсь с тем, как кэшировать ресурсы OGL (VAO, VBO, шейдеры и т. Д.) Для каждого узла рендеринга. Ниже приведены различные концепции кеширования, которые я уже придумал:
- Централизованный кеш, Каждый узел сцены имеет идентификатор, а средство визуализации имеет кэш, который отображает идентификаторы для визуализации узлов. Каждый узел рендеринга содержит VAO и VBO, связанные с геометрией. Промах кэша получает ресурсы и сопоставляет геометрию с узлом рендеринга в кэше. Когда геометрия изменяется, устанавливается грязный флаг. Если средство рендеринга видит флаг грязной геометрии во время итерации по узлам сцены, он создает буфер данных, используя узел рендеринга. Когда узел сцены удаляется, событие транслируется, и средство визуализации удаляет связанный узел визуализации из кэша при освобождении ресурсов. Кроме того, узел помечается для удаления, а средство визуализации отвечает за его удаление. Я думаю, что этот подход наиболее близко достигает цели 6, а также рассматривает 4 и 5. 2 страдает от дополнительной сложности и потери локальности данных при поиске карт вместо доступа к массиву.
- Распределенный кеш . Аналогично выше, за исключением того, что каждый узел сцены имеет узел рендеринга. Это обходит поиск карты. Для адресации данных узлы рендеринга могут быть сохранены в рендерере. Тогда узлы сцены могут вместо этого иметь указатели для визуализации узлов, а средство визуализации устанавливает указатель на промах кэша. Я думаю, что этот вид имитирует подход, основанный на компонентах, поэтому он будет соответствовать остальной архитектуре. Проблема здесь в том, что теперь узлы сцены содержат данные, специфичные для реализации рендерера. Если я изменю способ рендеринга вещей в рендерере (например, рендеринг спрайтов против томов), мне нужно изменить узел рендеринга или добавить больше «компонентов» в узел сцены (что также означает изменение графа сцены). С другой стороны, это кажется самым простым способом запустить и запустить мой рендер с первой итерацией.
- Распределенные метаданные . Компонент метаданных кэша рендерера хранится в каждом узле сцены. Эти данные не зависят от реализации, а содержат идентификатор, тип и любые другие соответствующие данные, необходимые для кэша. Затем поиск в кэше может быть выполнен непосредственно в массиве с использованием идентификатора, и тип может указывать, какой тип рендеринга использовать (например, спрайты против томов).
- Посетитель + распределенное отображение . Рендерер - это посетитель, а узлы сцены - это элементы в шаблоне посетителя. Каждый узел сцены содержит ключ кэша (например, метаданные, но только идентификатор), которым манипулирует только средство визуализации. Идентификатор может использоваться для массива вместо общего поиска карты. Рендерер может позволить узлу сцены отправлять другую функцию рендеринга в зависимости от типа узла сцены, и идентификатор может использоваться любым кешем. Идентификатор по умолчанию или идентификатор вне диапазона будет указывать на отсутствие кэша.
Как бы вы решили эту проблему? Или у тебя есть предложения? Спасибо за чтение моей стены текста!