2012-03-27 2 views
14

Я запускаю следующий код Scala. Он объединяет один список из 10 000 кубов. Затем он отображает их в цикле отображения с аниматором, который работает как можно быстрее. Но FPS - всего около 20. Я думал, что использование списков отображения сможет справиться с этим очень быстро. У меня есть ситуация, когда мне нужно отображать объекты 10k-100k. Есть ли лучший способ сделать это? В цикле отображения почти все, что он делает, это вызов gluLookAt и glCallList (это последний метод).Производительность OpenGL для 10 000 статических кубов

Я использую JOGL 2.0-RC5 от jogamp.org, который говорит, что поддерживает "OpenGL 1.3 - 3.0, 3.1 - 3.3, 4.0 ≥, ES 1.x и 2.x ES + почти все расширения поставщика"

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) 
    } 
} 
+0

какое оборудование вы используете? Включена ли двойная «буферизация»? –

+0

Я добавил 'caps.setDoubleBuffered (true)' и это не повлияло на производительность. Что касается аппаратного обеспечения, у меня есть графическая карта среднего уровня nvidia от года или два назад. Процессоры - это два двухъядерных Opteron от лет назад. – mentics

+0

Во-вторых, укажите версию OpenGL, которую вы используете. Указывает ли GL2 на OpenGL 2? _Oh_, это [JOGL] (http://jogamp.org/jogl/www/) и [GL2] (http://download.java.net/media/jogl/jogl-2.x-docs/ javax/media/opengl/GL2.html) означает, что это OpenGL * 3 *. Поиск _scala GL2_ не привел к большим количеству хитов ... –

ответ

10

Возможно, вам захочется подумать об использовании Vertex Buffer, который является способом хранения данных чертежа для более быстрого рендеринга.

Смотрите здесь для получения дополнительной информации:

http://www.opengl.org/wiki/Vertex_Buffer_Object

+0

Почему это говорит о том, что эта страница содержит устаревшие вещи? Устарели ли VBO или что на этой странице? Это сбивает с толку. – mentics

+1

@taotree: Он вызывает «glVertexPointer», «glTexCoordPointer» и другие вещи. Это было удалено. Буферные объекты все еще существуют.Я не собираюсь убирать эту страницу. –

+1

Я попробовал этот пример, который использует VBO: http://wadeawalker.wordpress.com/2010/10/17/tutorial-faster-rendering-with-vertex-buffer-objects/, и он смог сделать 1 миллион простых фигур в около 28 кадров в секунду. – mentics

4

Если вы храните информацию о вершинах в объекте буфера вершин, а затем загрузить его на OpenGL, вы, вероятно, увидите значительное увеличение производительности, особенно если вы рисуют статические объекты. Это связано с тем, что данные вершин остаются на графической карте, а не извлекаются из центрального процессора каждый раз.

+0

Я думал, что списки отображения хранят данные на графической карте. – mentics

1

Вы создаете список отображения, в котором вы вызываете drawItem для каждого куба. Внутри drawItem для каждого куба, который вы нажимаете и выталкиваете текущую матрицу преобразования, и между ними вращают и масштабируют куб, чтобы правильно разместить его. В принципе, это может быть результативным, поскольку преобразования в координатах куба могут быть предварительно вычислены и, следовательно, оптимизированы драйвером. Когда я пытался сделать то же самое (отображать много кубов, как в minecraft), но без вращения, то есть я использовал только glPush/glPopMatrix() и glTranslate3f(), я понял, что на самом деле эти оптимизации, т.е. избавление от ненужной матрицы, pops и applications, НЕ сделали мой драйвер. Так что примерно для 10-20K кубов я получил только около 40 кадров в секунду, а для 200K кубов - всего около 6-7 кадров в секунду. Затем я попытался выполнить переводы вручную, т. Е. Я добавил соответствующие векторы смещения в вершины своих кубов напрямую, т. Е. Внутри отображаемого списка не было матрицы push/pop и glTranslatef, я получил огромную скорость, поэтому мой код работал примерно в 70 раз быстрее.

Смежные вопросы