Производительность OpenGL для 10000 статических кубов - PullRequest
14 голосов
/ 27 марта 2012

Я использую следующий код Scala.Он составляет один список отображения из 10000 кубов.Затем он отображает их в цикле отображения с аниматором, который работает так быстро, как может.Но FPS составляет всего около 20. Я думал, что использование списков отображения сможет справиться с этим очень быстро.У меня есть ситуация, когда я должен иметь возможность отображать 10 000-100 000 объектов.Есть ли лучший способ сделать это?В цикле отображения почти все, что он делает, это вызывает 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)
  }
}

Ответы [ 3 ]

10 голосов
/ 27 марта 2012

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

См. Здесь обзор:

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

4 голосов
/ 27 марта 2012

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

1 голос
/ 13 июня 2012

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

...