LINUX.ORG.RU

OpenGL. Вывод графики [2D, Quads]

 ,


1

4

Всем привет, возник следующий вопрос. Можно ли как-то ускорить вывод графики через glBegin/glEnd или это совсем гиблый способ? Имеется довольно много объектов, которые следует вывести, и данный метод заметно тормозит, причем тормоза сильно отражаются и на процессоре. Насколько я знаю, при вызове данных функций данные передаются из оперативной памяти в видеопамять по довольно медленному соединению. Также, знаю, что лучше использовать VBO для ускорения вывода графики.

С VBO тоже проблемы. Знаю о нескольких типах буферов, из которых меня в данном контексте волнуют только буферы вершин, цветов и текстурных координат. Возникает законный вопрос, как среди тысяч прямоугольников, передаваемых в массиве, каждому из них назначить свою текстуру? Как повернуть каждый из них (замена glRotateF), как масштабировать (замена glScaleF), как задавать стиль наложения (glBlendFunc)?

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

1. Вызываем метод Draw движка для очередного прямоугольника. Передаем в него все необходимые параметры: Номер текстуры, Координаты (допустим, центра), Размеры, Угол поворота, Цвет, Прозрачность.

2. Движок добавляет координаты и иные параметры переданного прямоугольника в массив, сортирует их по нескольким массивам. На этом этапе, опять же, встают вопросы про использование таких параметров, как, например, угол поворота.

3. При вызове функции Redraw движка созданные массивы посылаются в память в качестве буферов и рисуются.

4. Также, при вызове некоторых других функций производится принудительная передача массивов в память, их рисование и очистка. К таким функциям относится, например, смена масштаба сцены (glScaleF), если предположить, что объекты, рисуемые с одним масштабом, передаются группами, друг за другом. Также, к таким функциям можно отнести glBlendFunc - для смены стиля наложения текстуры.

В общем, интересуют все идеи по данной теме. Заранее спасибо.

Можно ли как-то ускорить вывод графики через glBegin/glEnd или это совсем гиблый способ?

выкинь это древнее говно

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

там нормальное соединение (throughput, с latency похуже), проблема в том что возникают накладные расходы на содержание, обновление буферов в системной памяти. Отрисовка на современных GPU ведется при помощи пакетов, так вот этот пакет надо собрать, проставить там адреса, инициализировать конвейер итд. в случае immediate режима могут генериться много лишних пакетов.

VBO выгодно отличается тем, что может целиком распологаться в GPU local memory, то есть все для отрисовки уже содержится в gpu local mem

Возникает законный вопрос, как среди тысяч прямоугольников, передаваемых в массиве, каждому из них назначить свою текстуру? Как повернуть каждый из них (замена glRotateF), как масштабировать (замена glScaleF), как задавать стиль наложения (glBlendFunc)?

делаешь индексный буфер GL_ELEMENT_ARRAY_BUFFER, каждому индексу будет соответствовать полигон, цвет, текстурные координаты etc.

перед отрисовкой вызываешь glVertexAttribPointer.

рисуешь функцией glDrawElements.

Движок добавляет координаты и иные параметры переданного прямоугольника в массив, сортирует их по нескольким массивам. На этом этапе, опять же, встают вопросы про использование таких параметров, как, например, угол поворота.

все это легко делается шейдерными аттрибутами.

Есть ли смысл на каждом кадре полностью пересоздавать все буферы или надо менять все эти значения прямо в памяти? Мне подобный метод видится со следующей реализацией.

пересоздавать точно не имеет смысл.

лучше изменяемые параметры загнать в отдельный буфер, с нужными performance хинтами, лочить его через glMapBuffer (там еще много разных приколов с partial buffer updates), это дела синкается с gpu, вызывать отрисовку.

еще вариант - менять параметры прям в шейдерах, если они взаимонезависимы.

x4DA ★★★★★ ()
Последнее исправление: x4DA (всего исправлений: 5)

О конкретных вещах уже сказали, я ещё немного напомню принципы

  • Менять состояние OpenGL нужно как можно реже. Назначение отдельной текстуры на каждый полигон — это постоянное переключение состояний, поэтому текстуру желательно иметь одну («texture atlas»), и просто выдирать куски этой текстуры на подтекстуры с помощью текстурных координат. Трансформации обычно получается и на CPU обсчитывать.
  • В играх боевая единица обычно имеет свою личную текстуру на всё, или даже делит текстуру с ещё кем-то. Боевые единицы с одинаковой текстурой стараются рисовать в один проход, как один объект с пространственно разделённой геометрией. Но даже если не в один проход, всё равно будет приемлемая скорость.
  • В идеале буферы с геометрией надо держать в видеопамяти, пока они не меняюся. Где-то даже скелетную анимацию модели рассчитывают на стороне GPU с помощью шейдеров. Но и без этого будет приемлемая скорость.
quiet_readonly ★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.