# OpenGL / Jogle Code Reveiw zur Performance Verbesserung



## turing (15. Jul 2015)

Hallo Forum,

nach langer Pause steht mal wieder 3D auf dem Plan. Konkret geht es darum zu evaluieren, ob ein bestimmes Produkt bei uns im Hause auf 3D portiert werden kann. Ich habe dazu ein kleines Test-Programm geschrieben, dass die Größenordung etwas vereinfacht darstellt: Gegeben sind ca 15.000 Objekte, die 'recht' einfache Vertex-Daten besitzen, aber dennoch hat jedes Objekt grundsätzlich eine andere Forum. Jedes Objekt hat auch eine eigene Größe, Position und Rotation die sich zur Laufzeit ändert oder ändern kann (diese Werte werden an anderer Stelle geändert, das soll die Anzeige nicht interessieren, die hat es nur zu rendern).

Ich habe das Ganze in Jogl mit Indexed VBOs zusammengebaut und mal 15.000 Würfel gerendert (stimmt ja nicht ganz, ist für jedes Objekt eine eigenen Kontur - aber es ist ja auch nur eine erste Evaluation). An geeigneter Stelle wird ganz am Anfang für jedes Objekt ein VBO + IBO zusammengebaut und die Daten an die Grafikkartee übertragen (Beim Würfel also 8 Verticies und 36 Indicies). Im eigentlichen Loop fürs Rendern wird dann per for-Schleife für alle VBOs / IBOs ein glDrawElements() aufgerufen. Da die Translation, Skalierung und Rotation ja auch für jedes Objekt einzeln betrachtet werden müssen, wird ebenfalls entsprechend die MVP Matrix zusammengebaut und dass alles per Uniform an den Vertex Shader vorher übertragen. Vertex und Fragment Shader sind trivial. Hier der Code fürs Rendern:


```
public void display(GLAutoDrawable drawable) {
    trackDisplay();
    GL3 gl = getGL().getGL3();
    gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
    gl.glEnableVertexAttribArray(0);
    gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE); // only for testing
    for (GlObject object : objects) {
      float[] matMvp = makeModelViewProjectionMatrix(object);
      gl.glUniformMatrix4fv(mvpLocation, 1, false, matMvp, 0);
      gl.glUniform3f(colorLocation, 1, 1, 0);
      gl.glBindBuffer(GL.GL_ARRAY_BUFFER, object.getVbo());
      gl.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, 0, 0);
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, object.getIbo());
      gl.glDrawElements(GL.GL_TRIANGLES, object.getNum(), GL.GL_UNSIGNED_INT, 0);
    }
  gl.glDisableVertexAttribArray(0);
  }
```

Das funktioniert alles auch gut, auch mit Mouse-Camera etc. Aber mit meiner AMD Radeon HD 8790M komme ich gerade einmal auf 21-22 frames pro Sekunde (der Wert wird einmal pro Sekunde ausgegeben).


```
14 (71 ms per frame for 15625 objects)
22 (45 ms per frame for 15625 objects)
21 (47 ms per frame for 15625 objects)
22 (45 ms per frame for 15625 objects)
21 (47 ms per frame for 15625 objects)
22 (45 ms per frame for 15625 objects)
21 (47 ms per frame for 15625 objects)
22 (45 ms per frame for 15625 objects)
21 (47 ms per frame for 15625 objects)
```

Das erscheintt mir wenig. Die Garfikkarte ist zwar kaum eine Gamer Karte und betagt, aber ich hätte erwartet, dass man hier wesentlich mehr rausholen würde.... Meine Frage also an die Experten: Ist der obige Ansatz total verkehrt? Ist der Code einfach schlecht?[/code]


----------



## turing (15. Jul 2015)

PS: Nehme ich die Berechnung der MVP Matrix raus sowie die beiden Uniform-Übertragungen heraus, sind eine Handvoll mehr Frames pro Sekunde drin. Weit von meinem Ziel stabbil bei 60 FPS zu laufen.


----------

