# Android: OpenGL render performance Tipps ?



## KYL3R (12. Nov 2012)

Da die Suche nicht das gewünschte ergebnis lieferte, hier meine Frage an euch :

Habt ihr Tipps für den Umgang mit openGL unter Android ? Habe ein 1GHZ (single core) Handy mit ICS (4.0) und schreibe dafür ein Spiel. Der Hintergrund sind ein paar 3D Blöcke, der rest komplett 2D, ein paar Texturen etc. Ich bewege mich auf einer kleinen map, schieße max. 3 energiekugeln (sind animiert mit wenigen frames)
Ich nutzte gluLookAt um die Kamera zu verschieben.

Die Render methode braucht auf meinem Handy immer so zwischen 7 und 15 frames pro sekunde. bei 60 fps habe ich pro durchlauf nur 16,666 frames. Daher ist das aktuell mein Performance problem, deswegen hakt es ab und zu.

Nun wüsste ich gern, habt ihr Tipps für mich ? Wie am besten mit Texturen umgehen, mipmap ja oder nein ? Muss ich jedes mal die textur binden (texture.bind() ) um sie dann rendern zu können? Kann man nicht texturen, die sich nicht ändern (nicht animiert) "gebunden" lassen ? 
Oder ist es richtig, dass ich vor jedem Zeichnen die textur binde, und dann render ?
Ich wüsste gern allgemein ob einige von euch da Erfahrung gesammelt, und Tipps geben können, Kniffe und Tricks wie man beim rendern optimieren kann..


Würdet ihr allgemein zu einer Engine raten? Ich arbeite momentan nur mit Opengl.

Vielen Dank für Anregungen


----------



## Kr0e (12. Nov 2012)

Einen Tipp ? Nimm Unity3d wenn du Android und 3D machen willst.
Die haben tonnenweise optimiert. Mein Android spiel läuft auch auf älteren Geräten ohne Probleme.
Programmieren kannste in C#, also >= Java was Sprachsyntax angeh und daher sehr gut für Java-Leute.

Wenn es um ein akademisches Projekt geht und du nur daran interessiert bist WIE das ganze mit Java geht, dann musse mal profilen wo die Leistung bleibt. Unity3d kosten nämlich ein wenig und lohnt nicht wenn du die App nur zum Spaß/Eigenbedarf machst.

Zu deinen Fragen:

Ja, texture.bind ist leider nötig. Das bezeichnet man auch als Drawcall. Cleverer weise nutzt man gerade bei so schwachen Endgeräten nur EINE Textur mit allen Texturen als subtextures. So musst du nur einmal bind aufrufen.

Ggf. wäre OpenGL 3.x eine Verbesserung da du Shader benutzen kansst.


PS: Java ist halt hat ein paar grundlegende Probleme wenn es um 3D geht. Es gibt keine Strukturen, ergo landen alle Objekte auf dem Heap. Wenn es nun um Matrix/Vektor Mathematik geht, wo sehr oft sehr viele Instanzen gebruacht werden, geht der GC in die Knie. C# bietet hier Stackstrukturen an, ggf musst du bei Java da auf Libs zurückgreifen um das zu gewährleisten.

Wenn du bei Java bleiben willst, dann min. die Monkey Engine! Die ist wschon ganz ok, auch wenn es ein recht gewürfeltes Projekt ist... Alles alleine machen würde ich nicht. PCs vergeben dir mehr Performancefehler, AndriodHandys nicht.


----------



## KYL3R (12. Nov 2012)

Danke, wollte mir die Unity engine sowieso mal anschauen  Da gibt es doch auch eine kostenlose, darf man die komerziell nutzen ? Ich sehe auf der Seite, dass sie einige einschränkungen hat, aber zu dem Punkt lese ich nichts.
Wie ist das mit Werbung in Spielen (das Spiel ist dann free)? Gilt das als Komerzielle nutzung ? Das spiel wird ja nicht verkauft...

Ich programmier schon länger flash-games just for fun, jetzt bin ich in Android eingestiegen und würde gern auch irgendwann mal ein Spiel verkaufen oder eben mit Werbung arbeiten.

"Alles in eine Textur" das sehe ich öfter in spielen, jetzt versteh ich auch wieso.
Wenn ich eine Animation aus mehreren einzel Bildern habe, ist es aber doch egal, ob die in einem sind oder nicht, denn ich binde ein animationsframe pro drawcall, richtig ? 

Nur wenn ich mehrere Texturen auf einmal zeichnen will, ist es gut, wenn diese in einer Textur zusammengebastelt sind, weil ich "bind" vorgäng spare, und das bringt einiges, ja ? Hört sich gut an.

Mein Spiel ist nunmal fast fertig, daher wollte ich JETZT nicht auf ne Engine umsteigen, das plane ich für mein nächstes Spiel aber. Daher mein Interesse an der Unity Engine. 
Performancemäßig werde ich kaum noch Belastung hinzufügen, es ist wie gesagt fast fertig, ich muss nur noch ein bisschen optimieren. Werde versuchen "bind"s zu verringern  danke


----------



## Kr0e (12. Nov 2012)

Es gibt eine kostenlose Variante von Unity. Du darfst damit auch kommerzielle Produkte vermerkten, solange dein Einkommen nicht 100.000 pro Monat als Firma üersteigt. Bei Privatleuten also niemals 

Die Androiderweiterung kostet 400 dollar. Die Free Version läuft "nur" auf Windows, Mac und inzwischen sogar Linux + Webplayer (Wie ein Flashprogramm).

Für Spiele im Kleinsektor gibts eigentlcih keine bessere Alternative. Man zahlt einmalig diesen läppishcen Betrag und gut ist.

Aber es stimmt, die Free Variante ist eingeschränkt. Keine dynamischen Schatten und noch ein paar andere Einschränkungen. Ich kann aus Erfahrung sagen, dass man dennoch sehr gut zu recht kommt.
Und dynamische Schatten auf einem Androidgerät ? Nein danke... Da würde sowieso alles ruckeln.

PS: Vlt nochmal genau:

Unity unterscheidet sich in "Unity und Unity Pro".

Unity für PC, Mac und Linux ist free. Die Unity Pro Variante für PC, Mac und Linux kosteten 1500Dollar.
Unity für Android kostet 400 Dollar. Unity Pro für Android kostet ebenfalls 1500Dollar.
usw.


----------



## Titanpharao (13. Nov 2012)

Das klingt für mich überhaupt nicht nach einem Java Problem, sondern schlicht nach einem Problem in deinem Code.

Überlege mal, was in der Vergangenheit mit 1Ghz alles möglich war. UT2k3 z.b. ... da wirst du wohl paar Blöcke und 2D Texturen flüssig hinbekommen.

Auch bei meinem 2D Spiel war die Performance am Anfang total grottig. Dann habe ich nur eine Sache geändert, 


```
private IntBuffer vertices=null;

	public void setVertices(float[] vertices){
		tmpBuffer=new int[vertices.length];
		for(int i=0,j=0;i<vertices.length;i++,j++)
			tmpBuffer[j]=Float.floatToRawIntBits(vertices[i]);
		this.vertices=NIOUtil.intNIOBuffer(tmpBuffer);
	}

}
```

Aus dem FloatBuffer einen IntBuffer gemacht, was überall vorgeschlagen wird und auch bei meinem Anroid 2.3.4 noch nicht gefixt ist.
Intern ist ein Fehler (google) welcher ganz viel Speicherprobleme erzeugt. Das hat mich bei besonders vielen Objekten immer massiv an Performance gekostet. Jetzt kann ich weit über 1000 Sprites gleichzeitig zeichnen mit konstanten 60fps.

Desweiteren so wenig wie möglich JNI/OpenGL aufrufe im Code machen. Spritebatcher benutzen und wie Kr0e schon geschrieben hat, so viel wie möglich auf eine Texture und dann diese Objekte auch hintereinander rendern.

Wobei ich ~20 1024x1024 Texturen switche und dies auch keine Probleme ergibt.

"Beginning Android Games" gutes Buch, hat mir viel geholfen, z.b. auch den Float<=>Int Bug.

Sonst noch, wenns kein 3D ist, würde ich mitlerweile sogar zu normalem Java2D wechseln. Es ist so viel einfacher und schneller, wenn man sich in OpenGL nicht gut auskennt.

Hatte mir mal diverse Mini-Benchmarks geschrieben um zu sehen, was wirklich Performance kostet und was nicht ... zumindestens im 2D Bereich.


----------

