Простое любопытство к концепции графа сцены

Я пишу простой 3D-движок с использованием OpenGL. Я уже реализовал простой граф сцены со следующим шаблоном:

ISceneNode
    IMeshSceneNode
         StaticMeshSceneNode
    ICameraSceneNode
         StaticCameraSceneNode
         TrackBallCameraSceneNode
    ILightSceneNode
         PointLightSceneNode

Но мне интересно, может ли «Renderer» (класс, который реализует программу шейдера) также быть узлом сцены (извлечь код рендеринга из MeshSceneNode в RenderSceneNode). Для меня это может быть правильным выбором, потому что, если я должен визуализировать несколько мешей (например, 42 меша) с использованием одних и тех же вершинных и фрагментных шейдеров, было бы полезно связать и развязать шейдерную программу только один раз, а не 42 раза!

Итак, что вы думаете о следующих схемах:

Первый представляет мою текущую концепцию (ради простоты я не представляю узлы сцены «Свет» и «Камера»).

введите здесь описание изображения

Итак, здесь, если я хочу визуализировать свои 3 сетки (с 3 шейдерными программами, использующими одни и те же шейдеры), я буду привязывать и отвязывать свои шейдерные программы 3 раза для каждого кадра (в методе «рендеринга» каждого узла сетки).

Вот другая концепция:

введите здесь описание изображения

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

Что вы думаете о моей идее?


person user1364743    schedule 26.04.2014    source источник
comment
Все, что уменьшает количество серьезных изменений связанной программы шейдера GLSL, будет работать лучше (отмена привязки с помощью программы 0, когда вы закончите рисование, на самом деле довольно бессмысленна, просто оставьте это состояние в покое до тех пор, пока вы действительно нужно выполнить команду, которая связана с этим, и многие избыточные изменения будут работать сами собой). Программы GLSL и объекты фреймбуфера, как правило, являются самыми дорогими состояниями для изменения из-за сложной проверки состояния, которую должен выполнять драйвер. Изменение состояния вершин, униформы и т. д. намного дешевле.   -  person Andon M. Coleman    schedule 27.04.2014
comment
Идея, которую вы описываете, безусловно, использовалась раньше, и концептуально это была бы неплохая идея, однако имейте в виду, что дерево сцены представляет собой конгломерат [всех] ваших объектов, и эта идея меняет фундаментальное расположение узлов (что находится в оптимизированном графе с несколькими объектами), отменяя само применение графа сцены (иерархическое и логическое группирование объектов). Один объект теперь может иметь несколько листовых узлов, разбросанных по дереву, но не имеющих какого-либо логического общего предка.   -  person Lawrence Kok    schedule 27.04.2014
comment
Спасибо за ваши ответы. Итак, вы считаете, что граф сцены должен состоять только из мешей, камер, источников света и корня? часть рендеринга должна быть точной только в рамках метода «рендеринга» в узле сцены сетки? Таким образом, все узлы должны иметь общую матрицу преобразования (для рендерера это не так...). Итак, чтобы оптимизировать привязку моей шейдерной программы, мне нужно найти другое решение, но не в графе сцены? Это правильно ?   -  person user1364743    schedule 27.04.2014
comment
Да, граф сцены не обязательно будет генерировать оптимальный порядок графических команд. Вы всегда можете добавить дополнительный слой к своему программному обеспечению, чтобы взять пакеты, сгенерированные вашим графом сцены, и отсортировать их, чтобы свести к минимуму более дорогостоящие изменения состояния. Непрозрачная геометрия, например, не имеет большой зависимости от порядка, вы можете сортировать непрозрачные пакеты отрисовки по идентификатору шейдера, чтобы предотвратить изменение шейдера. Опять же, это работает лучше всего, если вы никогда не отвязываете шейдер; в правильно разработанном программном обеспечении нет особой необходимости отвязывать ресурсы, просто привязывайте что-то другое, когда вам нужно.   -  person Andon M. Coleman    schedule 27.04.2014
comment
На самом деле многое из того, что я только что упомянул, обсуждается здесь. Возможно, вам стоит прочитать детали реализации рендерера графа сцен Qt Quick.   -  person Andon M. Coleman    schedule 27.04.2014
comment
Итак, рендерер — это класс, целью которого является сбор в пакетах всей геометрии, необходимой для рендеринга, с минимальным количеством вызовов OpenGL, таких как glDrawArrays или glBindProgram. Таким образом, этот класс имеет ссылку на граф сцены и анализирует каждый узел, чтобы сделать несколько пакетов. Поэтому я думаю, что все эти шейдерные программы должны быть инициализированы из класса узлов сетки, например, в менеджере шейдерных программ, в котором хранятся все шейдерные программы, а после во время рендеринга класс рендерера будет использовать их, когда это необходимо (например, только одна шейдерная программа (привязка) для конкретного пакета). Это правильно ?   -  person user1364743    schedule 27.04.2014


Ответы (1)


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

Определение чистого API для вашего средства визуализации также позволит вам разделить ваши проблемы:

  • что рисовать, ср.
  • как это нарисовать.

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

person Shadocko    schedule 15.01.2015