Я разрабатываю 2D-игру на основе спрайтов для мобильных платформ и использую OpenGL (ну, собственно, Irrlicht) для рендеринга графики. Сначала я реализовал рендеринг спрайтов простым способом: каждый игровой объект визуализируется как квад с собственным вызовом отрисовки в графическом процессоре. Это означает, что если у меня было 200 игровых объектов, я делал 200 вызовов отрисовки на кадр. Конечно, это был плохой выбор, и моя игра была полностью привязана к процессору, потому что при каждом вызове отрисовки графического процессора было связано небольшое количество ресурсов процессора. GPU большую часть времени простаивал.
Теперь я подумал, что могу улучшить производительность, собирая объекты в большие партии и обрабатывая эти партии всего несколькими вызовами отрисовки. Я реализовал пакетную обработку (чтобы каждый игровой объект, имеющий одну и ту же текстуру, отображался в одном пакете) и подумал, что мои проблемы исчезли ... только для того, чтобы выяснить, что у меня частота кадров была даже ниже, чем раньше.
Почему? Ну, у меня есть 200 (или больше) игровых объектов, и они обновляются 60 раз в секунду. Каждый кадр мне приходится пересчитывать новую позицию (перемещение и вращение) для вершин в CPU (GPU на мобильных платформах не поддерживает создание экземпляров, поэтому я не могу сделать это там), и выполняю этот расчет 48000 в секунду (200 * 60 * 4, так как каждый спрайт имеет 4 вершины) просто кажется слишком медленным.
Что я могу сделать, чтобы улучшить производительность? Все игровые объекты движутся / вращаются (почти) в каждом кадре, поэтому мне действительно нужно пересчитать позиции вершин. Единственная оптимизация, о которой я мог подумать, - это таблица поиска поворотов, чтобы мне не пришлось их вычислять. Помогут ли точечные спрайты? Какие-нибудь неприятные хаки? Что-нибудь еще?
Спасибо.
источник
Я бы порекомендовал иметь VBO с каждой вершиной, содержащей положение / вращение каждого визуализированного объекта и пакетирование на основе текстуры, как вы делаете. Я не очень знаком с ogl ES, поэтому я не уверен, какую версию glsl он поддерживает, но вы можете даже иметь возможность пакетировать на основе набора текстур и сохранять, какую из 4 или около того текстур вы передаете в вы будете использовать внутри вершины. Точечные спрайты определенно повысят вашу производительность, потому что это значительно сократит объем передаваемых данных, и пакетная обработка никогда не должна снижать производительность, если вы делаете это правильно. Кроме того, вы могли бы немного улучшить производительность, вычисляя вращение на шейдере и передавая только значение типа int / float в params или внутри самой вершины. (параметры будут быстрее,
источник
Вы упоминаете мобильные платформы, которые не имеют экземпляров. Но у вас все еще есть вершинные шейдеры, не так ли?
В этом случае вы все равно можете выполнять псевдоинкестирование, что тоже очень быстро. Создайте VBO (GL_STATIC_DRAW) с угловыми точками (относительно центральной точки спрайта, например, -1 / -1, 1 / -1, 1/1, -1/1) и любыми нужными вам текстурными координатами. ,
Затем установите один из общих атрибутов вершины для каждого вызова отрисовки в центральной точке спрайта и нарисуйте два треугольника с ограниченным буфером. Внутри вершинного шейдера прочитайте общий атрибут вершины и добавьте координаты вершины.
Это избавит вас от блокировки передачи данных для каждого спрайта и должно быть намного быстрее. Фактическое количество вызовов отрисовки не так уж важно, между ними есть блокировка / остановка.
источник
Проблема заключается в количестве данных, которые вы отправляете в GPU каждый кадр. Просто создайте VBO для каждого пакета и заполните его один раз, затем примените соответствующие матрицы преобразования (через glMultMatrix или шейдер, если вы используете ES 2.0) при рисовании пакетов.
источник