Подтвердить что ты не робот

Ужасная потеря производительности при использовании Opengl FBO

Я успешно реализовал простую 2-мерную игру, используя lwjgl (opengl), где объекты исчезают, когда они уходят дальше от игрока. Это затухание было первоначально реализовано путем вычисления расстояния до начала каждого объекта у игрока и использования этого для масштабирования объектов альфа/непрозрачность.

Однако при использовании больших объектов этот подход кажется слишком грубым. Моим решением было реализовать масштабирование альфа/непрозрачности для каждого пикселя в объекте. Мало того, что это будет выглядеть лучше, но это также переместит время вычисления с CPU на GPU.

Я решил, что смогу реализовать его, используя FBO и временную текстуру.
Обратившись к FBO и замаскировав его с помощью предварительно вычисленной карты расстояния (текстуры) с использованием специального режима наложения, я намеревался достичь эффекта. Алгоритм выглядит так:

0) Инициализировать opengl и настроить FBO
1) Отображение фона стандартного буфера
2) Переключитесь на пользовательский FBO и очистите его
3) Рендеринг объектов (для FBO)
4) Маска FBO с использованием дистанционной текстуры
5) Переключение на стандартный буфер
6) Render временная текстура FBO (в стандартный буфер)
7) Элементы рендеринга hud

Немного дополнительной информации:

  • Временная текстура имеет тот же размер, что и окно (и, следовательно, стандартный буфер)
  • Шаг 4 использует специальный режим смешивания для достижения желаемого эффекта:
    GL11.glBlendFunc(GL11.GL_ZERO, GL11.GL_SRC_ALPHA);
  • Моя временная текстура создается с помощью фильтров min/mag: GL11.GL_NEAREST
  • Данные распределяются с использованием: org.lwjgl.BufferUtils.createByteBuffer(4 * width * height);
  • Текстура инициализируется с использованием: GL11.glTexImage2D (GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, ширина, высота, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, dataBuffer);
  • В моем коде нет ошибок GL.

Это действительно дает желаемые результаты. Однако, когда я сделал небольшое тестирование производительности, я обнаружил, что мой подход к FBO снижает производительность. Я тестировал, запрашивая 1000 последовательных визуализаций и измеряя время. Результаты были следующими:

В разрешении 512x512:

  • Обычный: ~ 1.7s
  • FBO: ~ 2.5s
  • (FBO -ступенчатый 6: ~ 1.7s)
  • (FBO -ступенчатый 4: ~ 1,7 с)

В разрешении 1680x1050:

  • Обычный: ~ 1.7s
  • FBO: ~ 7s
  • (FBO -ступенчатый 6: ~ 3,5 с)
  • (FBO -ступенчатый 4: ~ 6.0s)

Как вы можете видеть, эта шкала действительно ужасно. Чтобы сделать это еще хуже, я намереваюсь сделать второй проход этого типа. Машина, на которой я тестировалась, должна быть высокой в ​​плане моей целевой аудитории, поэтому я могу ожидать, что у людей будет намного меньше 60 кадров в секунду при таком подходе, что вряд ли приемлемо для этой игры.

Что я могу сделать, чтобы спасти производительность?

4b9b3361

Ответ 1

Как было предложено Damon и sidewinderguy, я успешно реализовал аналогичное решение, используя шейдер фрагмента (и вершинный шейдер). Моя производительность немного лучше, чем мои начальные вычисления на основе процессора, которые намного быстрее, чем мой FBO-подход. В то же время он дает визуальные результаты гораздо ближе к подходу FBO (перекрывающиеся объекты ведут себя немного иначе).

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

Кроме того, я очень благодарен за всю помощь, предложения и комментарии, которые я получил: -)