Main Menu

Frage zur Performance

Started by uwepost, June 05, 2013, 12:56:47 PM

Previous topic - Next topic

uwepost

Hallo liebe Experten!

Da wir gerade ein größeres Projekt umzusetzen beabsichtigen, wäre es schön, ein paar Erfahrungswerte zu kennen.
Womit skaliert die Framerate wie stark?
- Vertex-Anzahl, oder
- Dreieck-Anzahl, oder
- Dreieck-Flächen, oder
- Texturen-Auflösung, oder
- Objekt-Anzahl, oder
- was hab ich vergessen?
Anders gefragt: Wovon ist die Framerate am meisten abhängig, wovon am wenigsten?

Danke im Voraus!
Uwe

EgonOlsen

jPCT? Oder jPCT-AE? Und wenn jPCT, dann mit welchem Renderer?

uwepost

JPCT-ae.
Sorry, dass ich das nicht erwähnte...  :-X

EgonOlsen

Ok...das hängt letztendlich natürlich immer von der Szene und dem Endgerät ab, aber so ganz grob würde ich folgende Reihenfolge aufstellen:


  • Objekt-Anzahl
  • Vertex-/Dreieck-Anzahl
  • Dreieck-Flächen/Fillrate
  • Texturen-Auflösung/-Anzahl
Viele Objekte heißt viele Drawcalls und Drawcalls sind teuer. Von daher es sinnvoll, die Anzahl der Objekte zu minimieren. Es ist meistens besser, ein großes Objekt zu zeichnen als 3 kleine. Das gilt natürlich nur, wenn diese Objekte auch sichtbar sind. Nicht sichtbare Objekte sind schnell verworfen und kosten fast nichts.
Aber das ist wie gesagt etwas Geräte- bzw  GPU-abhängig. Bei den meisten Chips ist z.B. die Füllrate nicht so das Problem, bei NVidia Tegra aber schon. Adreno-Chips wiederum reagieren auf Drawcalls empfindlicher als andere und ältere PowerVRs mögen viele Vertices nur sehr bedingt.

Iridias

Was wäre denn eine gute Möglichkeit die Sichtbarkeit der vielen Objekte die da sind in Abhängigkeit von der Entfernung zur Kamera dynamisch zu ändern?

Ich hab schon versucht einen Thread im Hintergrund laufen zu lassen, der regelmäßig alle bekannten Objekte durchgeht, deren Entfernung feststellt und entsprechend die Sichtbarkeit setzt. Allerdings hab ich dabei entweder irgendetwas falsch gemacht, oder aber diese Mechanik kommt sich mit irgendwas anderem in die Quere, weil ich Objekte habe (in und außerhalb des Sichtbereichs) die aufpoppen und wieder verschwinden. Wenn das nur innerhalb des maximalen Sichtbarkeitsbereichs passieren würde, hätte ich "Config.maxPolysVisible" im Verdacht, aber da das auch außerhalb passiert, halte ich das für eher unwahrscheinlich (weil warum sollte die Engine, Objekte, die explizit auf visible(false) gesetzt sind, abhängig von maxPolysVisible wieder sichtbar machen?)


Die Sichtbarkeit setze ich grob wie folgt (nur halt in ner Schleife):

SimpleVector camPosition = world.getCamera().getPosition();
SimpleVector objectPosition = object.getTransformedCenter();
float distance = objectPosition.distance(camPosition);

if(distance > MAX_VIEW_DISTANCE) {
if(object.getVisibility()) {
object.setVisibility(false);
}
} else if(!object.getVisibility()) {
object.setVisibility(true);
}

EgonOlsen

#5
Wenn du das parallel zum Rendern machst, wirst du alle Arten von lustigen Seiteneffekten bekommen. jPCT-AE ist NICHT threadsicher. Wenn du das überhaupt so machen willst (eigentlich macht die Engine das ja selber, wenn die Objekte hinter der Farplane liegen), dann mache es in demselben Thread, der auch das rendern macht. Und es reicht dann auch


object.setVisibility(distance<= MAX_VIEW_DISTANCE);


Die ganzen ifs kannst du weglassen, setVisibility setzt nur ein einfaches Flag. Aber wie gesagt: Wenn du die Farplane ohnehin auf MAX_VIEW_DISTANCE setzt, kannst du dir das eigentlich sparen. Das ist nur sinnvoll, wenn du (wie ich z.B. in meinem Rollenspiel-Projekt) eine Art MVC einführst, d.h. Objekte in der Welt werden nur durch ein Object3D repräsentiert, wenn sie auch sichtbar sind, ansonsten sind es einfache Beans. Dann braucht man sowas natürlich irgendwie.

Iridias

Hmmm, ok, aber mit der Farplane geht ja nur "alles oder nichts".

Was ich in dem Beispiel noch nicht erwähnt hatte, war, dass ich da gerne noch zwischen Objekt-typen unterscheiden will.
Also, zB dass der Untergrund nie ausgeblendet wird und immer bis zur Farplane reicht. Und bei anderen Objekten das je nach Wichtigkeit staffeln. Dann würden zB Bäume (als unwichtiger Zierrat, der aber aufgrund der Menge viel Performance frisst) direkt nach Entfernung x ausgeblendet, Straßen oder ähnliches erst nach x+y usw.

So hat man auf der Karte die größtmögliche Übersicht bei akzeptabler Performance.

EgonOlsen

Quote from: Iridias on June 12, 2013, 02:12:43 PM
Was ich in dem Beispiel noch nicht erwähnt hatte, war, dass ich da gerne noch zwischen Objekt-typen unterscheiden will.
Also, zB dass der Untergrund nie ausgeblendet wird und immer bis zur Farplane reicht. Und bei anderen Objekten das je nach Wichtigkeit staffeln. Dann würden zB Bäume (als unwichtiger Zierrat, der aber aufgrund der Menge viel Performance frisst) direkt nach Entfernung x ausgeblendet, Straßen oder ähnliches erst nach x+y usw.
Das ist richtig, das mache ich auch so. Bäume und Boden sind bei mir "immer" sichtbar, Büsche werden später eingeblendet, Grass noch später usw...aber in dem Fall lohnt es sich meiner Meinung nach wirklich, über eine Trennung von Darstellung (Object3D) und Model (irgendwas anderes, schlankeres) nachzudenken und die Sichtbarkeit dann lieber grob auf Basis des Models zu prüfen.

Als Beispiel mal meine Weltkarte aus Sicht der AI: http://www.jpct.net/forum2/index.php/topic,2471.msg24522.html#msg24522

Die kleinen roten Punkte sind Bäume und Büsche. Die könnte ich gar nicht alle direkt in Object3Ds packen, weil dann der Speicher platzen würde.

Iridias

Also vom Prinzip her einen hintergrund-thread, der über die Liste aller Items/dummy-beans interiert und deren sichtbarkeit bestimmt und die sichtbaren in einer extra-liste pflegt, die dann wiederum vom Render-thread heran gezogen werden kann um zu bestimmen welche Object3D benötigt werden.

Das wäre zumindest der einzige Ansatz, der mir einfällt um zu vermeiden, im Render-thread jedes mal alle Items durch-iterieren und checken zu müssen (was ja absolut inperformant wäre).

Was wäre denn dann zum handlen der Object3Ds die performanteste Strategie? Für jeden Item-type ein "template-object" haben und diese "on-demand" clonen und positionieren? Oder einen pool an objekten haben deren nicht benutzte Objekte nur neu positioniert und sichtbar gemacht werden müssen?

EgonOlsen

Ich würde das im Renderthread machen. Wenn man ein paar Early-Out-Bedingungen ergänzt und evtl. eine einfache Einteilung der Objekte in eine gröbere Struktur (ich verwende z.B. ein einfaches Gitter, also kein Quadtree oder so) einführt, dann ist das auch für tausende von Objekten machbar.

Wenn du das in einem anderen Thread machst, musst du den entweder mit dem Renderthread synchronisieren (dann hast du nichts gewonnen) oder du zeichnest lauter lustige Zwischenstände. Bestes Beispiel: Der Spieler macht eine Drehung um 180 Grad...was macht dann dein Thread? Wenn er noch an der alten Ansicht rechnet, rendert der Renderthread schlichtweg nichts, weil der Thread die neue Sichtbarkeit noch nicht berechnet hat. Das gleiche Problem hast du bei jeder Drehung, wenn auch vielleicht nicht so extrem.

Ich rate im Bereich Spiele von Threads ab, sofern es irgendwie anders geht. Und hier geht es meiner Ansicht nach auch anders. Ich messe nachher mal nach, wie lange sich mein Krams in der Sichtbarkeitsermittlung aufhält...einfach als kleine Referenz.

EgonOlsen

Nachtrag: Ich habe meine Sichtbarkeitsprüfung mal vermessen...ich brauche auf einem Nexus4 für 8150 Objekte, deren Sichtbarkeit jeden Frame im Renderthread berechnet wird, lediglich 4,5ms durch Durchlauf. Das ist Ding ist natürlich ziemlich optimiert und verwendet wie gesagt zusätzlich eine Art Gittermodel, um große Teile der Objekte schnell zu verwerfen. Ich schätze, eine naive Implementierung als Startpunkt für weitere Optimierungen sollte so etwa bei 12ms liegen.

Iridias

Danke für die vielen Hinweise.
Ich habe in meinem Code einiges umgebaut und verbessert und liegen beim prüfen der Sichtbarkeit jetzt bei so 8 - 10 ms. Das tatsächliche sichtbar- und unsichtbar schalten hab ich auch noch optimiert, sodass er im Schnitt jetzt 10 - 15 ms braucht... statt vorher 80 - 100 ms. Da ich das wie empfohlen im Render-thread mache, kommt das der FPS spürbar zugute!
Und flackern tut jetzt auch nix mehr.