Ответ 1
Возможно, вам захочется подумать об использовании Vertex Buffer, который является способом хранения информации о чертеже для более быстрого рендеринга.
См. здесь обзор:
Я запускаю следующий код Scala. Он объединяет один список из 10 000 кубов. Затем он отображает их в цикле отображения с аниматором, который работает как можно быстрее. Но FPS - всего около 20. Я думал, что использование списков отображения сможет справиться с этим очень быстро. У меня есть ситуация, когда мне нужно отображать объекты 10k-100k. Есть ли лучший способ сделать это? В цикле отображения почти все, что он делает, это вызов gluLookAt и glCallList (это последний метод).
Я использую JOGL 2.0-rc5 от jogamp.org, который говорит, что поддерживает "OpenGL 1.3 - 3.0, 3.1 - 3.3, ≥ 4.0, ES 1.x и ES 2.x + почти все расширения поставщиков"
class LotsOfCubes extends GLEventListener {
def show() = {
val glp = GLProfile.getDefault();
val caps = new GLCapabilities(glp);
val canvas = new GLCanvas(caps);
canvas.addGLEventListener(this);
val frame = new JFrame("AWT Window Test");
frame.setSize(300, 300);
frame.add(canvas);
frame.setVisible(true);
}
override def init(drawable: GLAutoDrawable) {
val gl = drawable.getGL().getGL2()
gl.glEnable(GL.GL_DEPTH_TEST)
gl.glNewList(21, GL2.GL_COMPILE)
var i = -10.0f
var j = -10.0f
while (i < 10.0f) {
while (j < 10.0f) {
drawItem(gl, i, j, 0.0f, 0.08f)
j += 0.1f
}
i += 0.1f
j = -10f
}
gl.glEndList()
val an = new Animator(drawable);
drawable.setAnimator(an);
an.setUpdateFPSFrames(100, System.out)
an.start();
}
override def dispose(drawable: GLAutoDrawable) {
}
override def reshape(drawable: GLAutoDrawable, x: Int, y: Int, width: Int, height: Int) {
val gl = drawable.getGL().getGL2();
val glu = new GLU
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(10, 1, -1, 100);
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
}
def drawBox(gl: GL2, size: Float) {
import Global._
gl.glBegin(GL2.GL_QUADS);
for (i <- 5 until -1 by -1) {
gl.glNormal3fv(boxNormals(i), 0);
val c = colors(i);
gl.glColor3f(c(0), c(1), c(2))
var vt: Array[Float] = boxVertices(boxFaces(i)(0))
gl.glVertex3f(vt(0) * size, vt(1) * size, vt(2) * size);
vt = boxVertices(boxFaces(i)(1));
gl.glVertex3f(vt(0) * size, vt(1) * size, vt(2) * size);
vt = boxVertices(boxFaces(i)(2));
gl.glVertex3f(vt(0) * size, vt(1) * size, vt(2) * size);
vt = boxVertices(boxFaces(i)(3));
gl.glVertex3f(vt(0) * size, vt(1) * size, vt(2) * size);
}
gl.glEnd();
}
def drawItem(gl: GL2, x: Float, y: Float, z: Float, size: Float) {
gl.glPushMatrix()
gl.glTranslatef(x, y, z);
gl.glRotatef(0.0f, 0.0f, 1.0f, 0.0f); // Rotate The cube around the Y axis
gl.glRotatef(0.0f, 1.0f, 1.0f, 1.0f);
drawBox(gl, size);
gl.glPopMatrix()
}
override def display(drawable: GLAutoDrawable) {
val gl = drawable.getGL().getGL2()
val glu = new GLU
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
gl.glLoadIdentity()
glu.gluLookAt(0.0, 0.0, -100.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f)
gl.glCallList(21)
}
}
Возможно, вам захочется подумать об использовании Vertex Buffer, который является способом хранения информации о чертеже для более быстрого рендеринга.
См. здесь обзор:
Если вы храните информацию о вершинах в объекте буфера вершин, а затем загружаете ее в OpenGL, вы, вероятно, увидите значительное увеличение производительности, особенно если вы рисуете статические объекты. Это связано с тем, что данные вершин остаются на графической карте, а не извлекаются из центрального процессора каждый раз.
Вы создаете список отображения, в котором вы вызываете drawItem для каждого куба. Внутри drawItem для каждого куба вы нажимаете и выталкиваете текущую матрицу преобразования, а между ними вращают и масштабируют куб, чтобы правильно поместить его. В принципе это может быть преобразования по координатам куба могут быть предварительно вычислены и, следовательно, оптимизированы драйвером. Когда я пытался сделать то же самое (отображать много кубов, как в minecraft), но без вращения, то есть я использовал только glPush/glPopMatrix() и glTranslate3f(), я понял, что на самом деле эти оптимизации, т.е. избавление от ненужной матрицы, pops и applications, НЕ сделали мой драйвер. Так что примерно для 10-20K кубов я получил только около 40 кадров в секунду, а для 200K кубов - всего около 6-7 кадров в секунду. Затем я попытался выполнить переводы вручную, т.е. Я добавил соответствующие векторы смещения непосредственно в вершины своих кубов, т.е. Внутри отображаемого списка не было матрицы push/pop и glTranslatef, я получил огромную скорость, поэтому мой код работал примерно в 70 раз быстрее.