2017-02-03 10 views
0

Я пытаюсь реализовать отложенный рендеринг на телефоне Android с помощью OPENGL ES 3.0. Я получил это, чтобы работать нормально, но только очень медленно, что скорее поражает весь смысл. Что действительно замедляет работу, это несколько вызовов шейдеров. Вот, вкратце, то, что мой код делает:Есть ли что-нибудь, что я могу сделать с накладными расходами от запуска шейдера несколько раз

  1. Геометрия Pass:

    Рендер сцены - выход положение, нормальный и цвет кремовый экрана буферов.

  2. Для каждого источника света:

    а) Трафарет Pass:

    Рендер сферу в текущей позиции света, сортируют по размеру в соответствии с интенсивностью света. Отметьте эти пиксели под воздействием текущего света. Нет фактического выхода.

    б) Light Pass:

    Рендер сферы снова, на этот раз, используя данные из геометрии прохода применять световые уравнения для пикселей, отмеченных в предыдущем шаге. Добавьте это в буфер закадрового

  3. Blit экранировать

Это это перезапуск шейдеров для каждого источника света, вызывающего узкого место. Например, при 25 лампах вышеуказанные шаги работают со скоростью около 5 кадров в секунду. Если вместо этого я сделаю: Geometry Pass/Stencil Pass - нарисуйте 25 огней/Light Pass - нарисуйте 25 огней, они работают со скоростью около 30 кадров в секунду. Итак, кто-нибудь знает, как я могу избежать повторной инициализации шейдеров? Или, по сути, просто объясните, что занимает время? Помогло бы или даже было бы возможно (и мне жаль, если это звучит глупо), чтобы сохранить шейдер «открытым» и перезаписать предыдущие данные, а не делать все, что требуется, так много времени перезапускает шейдер? Или я должен дать это как метод для многократного освещения, в любом мобильном устройстве.

ответ

0

Ну, я решил проблему обмена шейдерами для каждого света, используя целую текстуру в виде карты трафарета, где определенный бит установлен для представления каждого света. (Таким образом, ограничено 32 индикаторами.) Это означает, что шаг 2a (выше) может быть закольцован, затем одно изменение шейдера и этап 2b петли. Тем не менее, (ахахаха!) Выясняется, что это действительно не ускорило ситуацию, поскольку это не так, в конце концов, замена шейдеров - вот проблема, но изменение назначения записи. То есть, несколько вызовов до glDrawBuffers. Поскольку у меня было два таких вызова в цикле создания трафарета: один рисовать нигде при рисовании сферы для вычисления того, на какие пиксели влияет, и на рисование целочисленной текстуры, используемой в качестве карты трафарета. Я, наконец, понял, что, когда я использую blending (каждый пишут с цветом, где находится один бит), не имеет значения, буду ли я писать на этапе вычисления пикселя, если он со всеми нулями. Избавление от ненужных звонков до glDrawBuffers берет FPS от одиночных цифр до высоких двадцатых.

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

Я хотел бы сказать, что код был написан только для того, чтобы убедиться, что это жизнеспособный метод, и может быть сделано множество небольших оптимизаций. Кстати, поскольку мне было ограничено 4 рисования буферов, мне пришлось поцарапать карту положения, а вместо этого восстановить это с gl_FragCoord.xyz. У меня нет надлежащих инструментов для сравнения, поэтому мне было бы интересно услышать от всех, кто может сказать мне, какая разница, что происходит быстрее.