10,000个静态立方体的OpenGL性能

时间:2012-03-27 04:20:26

标签: performance scala opengl jogl

我正在运行以下Scala代码。它编译10,000个立方体的单个显示列表。然后它在显示循环中显示它们,动画师尽可能快地运行。但FPS只有20左右。我原以为使用显示列表可以很快处理这个问题。我有一种情况需要能够显示10k-100k的物体。有没有更好的方法呢?在显示循环中,几乎所有操作都是调用gluLookAt和glCallList(这是最后一种方法)。

我正在使用jogamp.org的JOGL 2.0-rc5,它说它支持“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 个答案:

答案 0 :(得分:10)

您可能需要考虑使用顶点缓冲区,这是一种存储绘图信息以便更快渲染的方法。

请点击此处查看概述:

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

答案 1 :(得分:4)

如果将顶点信息存储在顶点缓冲区对象中,然后将其上传到OpenGL,您可能会看到性能大幅提升,尤其是在绘制静态对象时。这是因为顶点数据保留在图形卡上,而不是每次都从CPU中取出。

答案 2 :(得分:1)

您可以创建一个显示列表,在其中为每个多维数据集调用drawItem。里面的drawItem 对于每个立方体,您可以推送并弹出当前的变换矩阵,并在其间旋转并缩放立方体以正确放置它。原则上,自从以来可能是高效的 立方体坐标上的变换可以预先计算,因此由驱动程序优化。当我试图做同样的事情(显示很多立方体,如在我的世界中)但没有旋转,即我只使用glPush / glPopMatrix()和glTranslate3f(),我意识到实际上这些优化,即摆脱不必要的矩阵推/弹出窗口和应用程序,不是由我的司机完成的。所以对于大约10-20K的立方体,我只有大约40fps,200K立方体只有大约6-7 fps。 然后,我尝试手动进行翻译,即我将相应的偏移向量直接添加到我的立方体的顶点,即在显示列表内部没有矩阵推/弹,也没有glTranslatef,我得到了一个巨大的加速,所以我的代码运行速度快了70倍。