Лучший способ переместить спрайты в OpenGL - перевести или изменить вершины - PullRequest
5 голосов
/ 12 декабря 2011

Я создаю приложение для Android с использованием openGL ES. Я пытаюсь нарисовать в 2D множество движущихся спрайтов, которые отскакивают от экрана.

Давайте рассмотрим, у меня есть шар с координатами 100,100. Изображение шара имеет ширину 10px, поэтому я могу создать вершины boundingBox = {100,110,0, 110,110,0, 100,100,0, 110,100,0} и выполнить следующее для каждого цикла onDrawFrame() с загруженной текстурой шара.

//for each ball object
FloatBuffer ballVertexBuffer = byteBuffer.asFloatBuffer();
ballVertexBuffer.put(ball.boundingBox);
ballVertexBuffer.position(0);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, ballVertexBuffer); 
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0,4);

Затем я бы обновил массив boundingBox, чтобы перемещать шары по экрану.

В качестве альтернативы, я вообще не мог изменить bounding box и вместо этого translatef() шарик до рисования вершин

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, ballVertexBuffer); 
gl.glPushMatrix();
gl.glTranslatef(ball.posX, ball.posY, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0,4);
gl.glPopMatrix();

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

Ответы [ 2 ]

3 голосов
/ 12 декабря 2011

OpenGL ES (по состоянию на 2.0) не поддерживает инстанцирование, к несчастью. Если бы это произошло, я бы порекомендовал рисовать 2-треугольный спрайт, инстанцированный N раз, считывая смещения x / y центральной точки и, возможно, значение масштаба, если вам нужны спрайты разного размера, из текстуры вершины. (который ES поддерживает просто отлично). Это ограничит объем данных, которые вы должны выдвинуть за кадр, до минимума.

Предполагая, что вы не можете выполнить симуляцию непосредственно на графическом процессоре (таким образом, избегая загрузки данных вершин в каждом кадре) ... это в основном оставляет вам только одну эффективную опцию:
Создайте 2 VBO, сопоставьте одно и заполните его, в то время как другое используется в качестве источника вызова отрисовки. Вы также можете сделать это , по-видимому, с одним буфером, если вы между ними glBufferData(... 0), что говорит OpenGL сгенерировать новый буфер и выбросить старый, как только он завершит чтение из него.

Потоковые вершины в каждом кадре могут быть не очень быстрыми, но это не имеет значения, если задержка может быть хорошо скрыта (например, при рисовании из одного буфера при заполнении другого). Немного вызовов отрисовки, мало изменений состояния и, в идеале, никаких остановок все равно должно быть быстрым.

1 голос
/ 12 декабря 2011

Рисование вызовов намного дороже, чем изменение данных. Кроме того, glTranslate не так эффективен, как просто добавление нескольких чисел, в конце концов, он должен пройти полное умножение матрицы 4 × 4, то есть 64 скалярных умножения и 16 скалярных сложений.

Конечно, лучший метод - это использовать инстансы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...