График сцены для отложенного рендеринга

10

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

В обычном (движок прямого рендеринга) я просто добавил бы все элементы (все реализующие IDrawable и IUpdateAble) в мой граф сцены, а затем сначала переместился в ширину графа сцены и вызвал Draw () везде.

Однако в механизме отложенного рендеринга я должен разделять вызовы отрисовки. Сначала я должен нарисовать геометрию, затем тени и затем источники света (все для разных целей рендеринга), прежде чем объединить их все. Так что в этом случае я не могу просто перемещаться по графу сцены и просто вызывать Draw. То, как я это вижу, мне нужно либо проехать по всему графу сцены 3 раза, проверяя, что это за объект, который нужно нарисовать, или мне нужно создать 3 отдельных графа сцены, которые каким-то образом связаны друг с другом. Оба эти решения кажутся плохими, я бы хотел сделать объекты сцены более прозрачными.

Еще одно решение, о котором я подумал, - это как обычно проходить через граф сцены и добавлять элементы в 3 отдельных списка, разделять геометрию, тени и источники света, а затем повторять эти списки, чтобы нарисовать правильные вещи, это лучше, и так ли это? целесообразно заполнить 3 списка каждый кадр?

Рой Т.
источник

Ответы:

6

Подход, который я использовал в проекте C ++, состоит в том, что граф сцены (который имеет пространственный индекс) заполняет «видимый» попадание std :: vector, основываясь на текущем усмотрении просмотра. Этот видимый список управляется графом сцены, поэтому он пересчитывается только при перемещении камеры - движущиеся объекты на графике перемещаются в этом списке с использованием надгробий и несортированных списков изменений, которые сортируются и объединяются по мере необходимости.

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

Таким образом, рисование проходит через видимый массив за один проход, и за этот проход создается связанный список этих элементов для повторного посещения, и они получают второй проход и так далее.

Рисование спереди назад и непрозрачный, а затем прозрачный помогает сохранить все в порядке.

Возможно, это не сводит к минимуму количество изменений шейдеров и т. Д., Но это довольно выполнимо и просто для реализации.

Я понятия не имею о XNA и о том, насколько это применимо, и как много боязни вы создаете. Однако было бы очень интересно узнать, что ветераны думают об этом подходе для C ++ RTS.

Будет
источник
Привет, Уилл, мне действительно нравится этот ответ, особенно потому, что он полностью отличается от того, о чем я думал до сих пор. Ваш метод кажется очень разумным, особенно когда речь идет о полупрозрачных объектах (которых я до сих пор избегал). Создание (связанного) списка из графа сцены для объектов, которые нужно посетить, кажется очень хорошей идеей. И да, в XNA мы тоже должны делать все эти вещи низкого уровня :).
Рой Т.
3

Моим предложением будет двухэтапный подход с учетом ваших конкретных требований, аналогичный тому, что вы описали сами. Вам нужен граф сцены и «коллекция визуализации» для каждого из этапов рендеринга, в вашем случае тень, геометрия, источники света (возможно, четвертый - это прозрачные объекты?)

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

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

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

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

Поскольку ваши структуры данных имеют быструю вставку и не генерируют мусор, за повторное заполнение списков, как вы упомянули, штраф не взимается.

рынок
источник