Leitfaden performancefreundlicher Fahrzeugbau
Hinweis: Dieser Artikel wurde noch nicht ins Englische übersetzt!
Wie der Name schon sagt, soll dieser Leitfaden Möglichkeiten und Denkanstöße bieten, OMSI-Fahrzeuge möglichst performance-freundlich zu gestalten.
Ein OMSI-Fahrzeug besteht aus 3D-Modellen, Texturen, Sound und Script – und in allen vier Bereiche kann man hinsichtlich der Performance sehr viel falsch machen!
Inhaltsverzeichnis
- 1 3D-Modelle
- 1.1 Theorie
- 1.2 Nicht zuviele o3d-Dateien und nicht zuviele einzelne Texturen
- 1.3 Verwendung von reduzierter Darstellung für die Entfernung und für KI-Fahrzeuge
- 1.4 Nicht übermäßig viele Vertices verwenden - Texturen können auch sinnvolle Dienste leisten
- 1.5 Vertices nur da einbauen, wo es auch sinnvoll ist
3D-Modelle
Theorie
Zunächst muss der Begriff 'Drawcall' definiert werden:
Zwar wird der Bus (wie alles andere) aus einzelnen Dreiecken gezeichnet, die Dreiecke ihrerseits sind aber zusammengefasst zu Meshs mit gleichen Materialeigenschaften, Texturen und so weiter. Einen solchen zusammengefassten Zeichenvorgang bezeichnet man als Drawcall. Intern wird dieser zunächst von OMSI vorbereitet, dann werden alle Parameter der Grafikkarte übergeben und schließlich arbeitet die Grafikkarte "eigenständig" den Drawcall mit allen zugehörigen Dreiecken ab.
Dieser Zusammenhang erklärt auch, warum ein Drawcall mit 100.000 Vertices wesentlich schneller abgearbeitet wird, als 1000 Drawcalls mit jeweils 100 Vertices.
Nicht zuviele o3d-Dateien und nicht zuviele einzelne Texturen
Jede o3d-Datei verursacht mindestens einen Drawcall pro Textur, die die o3d-Datei verwendet. In bestimmten Fällen und insbesondere auch bei x-Dateien können es sogar mehrere Drawcalls pro Textur und o3d-Datei sein.
Hieraus ergeben sich folgende Regeln:
Verwende so wenig o3d-Dateien wie möglich pro Bus.
Unumgänglich ist eine Separierung bei Animationen und oft bei transparenten Dingen, bei denen über die Separierung die Renderreihenfolge festgelegt wird. Daran kann man nicht rütteln.
Es ist aber ohne weiteres möglich, das Fahrzeug nur aus sehr wenigen nicht-animierten o3d-Dateien zusammen zu setzen, z.B. (Reihenfolge = Renderreihenfolge):
- Innenmesh inkl. Fahrerarbeitsplatz ohne Leuchtmelder, Schalter usw.
- Transparenzen im Innenraum
- Außenmesh
- Fensterscheiben von innen
- Fensterscheiben von außen
Innerhalb einer o3d-Datei so wenig unterschiedliche Texturen wie möglich.
Mit der obigen Erklärung wohl einfach zu verstehen: Wenn mein komplettes Außenmesh nur eine Textur hat, dann ist es auch nur ein Drawcall. Das ist besser als wenn mein Außenmesh zwei Texturen benötigt, sodass das Außenmesh in zwei Drawcalls gerendert werden muss.
Wird ein Bauteil ohnehin immer animiert (typisches Beispiel: Räder), dann ist es weniger tragisch, wenn deren Textur separat ist. Allerdings sollten auch die LODs berücksichtigt werden: Da unsere Fahrzeuge in größerer Entfernung keine animierten Räder haben, haben wir die Radtextur auch in die Haupttextur integriert.
Verwendung von reduzierter Darstellung für die Entfernung und für KI-Fahrzeuge
Mit Hilfe von LODs ist es möglich, dass das Fahrzeug auf größerer Entfernung einfacher gezeichnet wird. Und auch, wenn der User es nicht selbst verwendet, sollte es einfacher werden.
Jedes Fahrzeug sollte mindestens über zwei LOD-Stufen verfügen, sodass es ab unter etwa 10% Bildschirmgröße zu einer starken Vereinfachung kommt.
In dieser Größenordnung kann bereits auf den Innenraum komplett verzichtet werden, die äußere Hülle sollte nur noch ein sehr einfaches Mesh sein (20-50 Vertices). Wir haben außerdem auf Nachttexturen und Lichteffekte in dieser Entfernung komplett verzichtet. Man muss ja nur noch sehen, "dass da ein Bus fährt".
Jedes Fahrzeug sollte als KI-Fahrzeug wesentlich vereinfacht werden. (Obgleich unpräzise, ist mit "KI-Fahrzeug" auch ein "verlassenes" Userfahrzeug gemeint. Sämtliche Flags, wie die folgende, die sich auf diese Nomenklatur beziehen, stufen verlassene Userfahrzeuge als KI-Fahrzeuge ein.)
Hierzu dient der Viewpoint-Befehl. Die darunterstehende Zahl kann folgende Werte annehmen:
- 0 = immer sichtbar
- 1 = am aktuellen Userfahrzeug nur von außen sichtbar
- 2 = am aktuellen Userfahrzeug nur von innen sichtbar
- 3 = 1 + 2, also am aktuellen Userfahrzeug von innen und außen sichtbar
- 4 = nur an KI-Fahrzeugen sichtbar.
- 5 = 4 + 1, also an KI-Fahrzeugen sichtbar oder am Userfahrzeug nur von außen
- 6 = 2 + 4, also an KI-Fahrzeugen sichtbar oder am Userfahrzeug nur von innen
- 7 = 1 + 2 + 4, also immer sichtbar, dann kann man auch die 0 nehmen! :)
Zu beachten ist: Ein KI-Fahrzeug sieht man sich nur von außen an, aber meist nicht so genau. Es kann aber sehr dicht stehen und man guckt oft auch mal von hinten rein (an der Ampel oder Haltestelle).
- KI-Fahrzeuge sollten daher das komplette, detaillierte Außenmesh haben und die groben Dinge des Innenmeshs, wie Verkleidungen, Sitze usw. Hierbei sind vor allem die Dinge wichtig, die man von hinten sieht.
- KI-Fahrzeuge brauchen nicht über ein animiertes Cockpit verfügen (animierter Sitz, Lenkrad) und Haltestangen kann man auch wesentlich vereinfachen. Theoretisch gilt das auch für den eigenen Bus in der Außenansicht, aber hier muss man nicht so sparsam sein, da der eigene Bus ja nur einmal sichtbar ist - KI-Fahrzeuge dagegen oft in großer Zahl.
- Sehr viel Potenzial bieten wieder Drawcalls: Typischerweise gibt es bei aller Optimierung mehrere Texturen für den Innenraum, oft aber nur eine für das Außenmesh. Sinnvollerweise also sollte man soviele Texturen des Innenraums wie möglich einsparen. Das statische Dashboard, das Lenkrad, die übriggebliebenen Haltestangen usw. benutzen oft separate Texturen; dies alles sollte im KI-Mesh über einen kleinen Bereich einer weiterhin notwendigen Textur gemappt werden, z.B. eine simple dunkelgraue, leicht "angerauhte" Fläche. Aber Achtung: Es bringt erst dann was, wenn eine oder mehrere komplette Texturen eingespart werden.
Das KI-Modell des SD77 als Beispiel
Das KI-Innenmesh des SD77 benötigt lediglich die Texturen SD77_02.bmp, _03.bmp und _04.bmp. Eingespart werden die Texturen Fahrersitz, Panel, Thermometer und Zahltisch gegenüber dem User-Innenraum:
Unterschiede KI- und User-Mesh beim SD77. In der Ansicht von Hinten erkennt man die nur geringen Unterschiede, die vor allem Mesh-Vereinfachungen mit größerem Poly-Reduktionspotential besitzen: Haltestangen, Haltewunschknöpfe, Griffe an den Sitzen. Wichtige Details wie die Sitze, Treppenwangen oder auch Leuchten müssen beibehalten werden:
Nicht übermäßig viele Vertices verwenden - Texturen können auch sinnvolle Dienste leisten
Damals™, als wir im Flusi mit dem Modellbau angefangen haben, mussten wir noch das Mesh per Hand auf Millimeterpapier zeichnen und die Koordinaten selbst ausmessen und maßstäblich umrechnen. Dann haben wir uns an die Lochkarten-Stanzmaschine gesetzt und wehe, wenn wir einen Fehler gemacht haben... ok, genug der angestaubten Geschichten von früher™! :-D (Wobei der Anfang noch stimmt, die Design-Programme für den Flusi kamen erst mit den Versionen 2000/2002 mit FSDS und Gmax so richtig in Schwung...)
Was ich mit der kleinen Geschichte von "damals als wir nix hatten" sagen will: Schon aus Egoismus heraus war man mit Polys und Vertices sparsam. Das bleibt so drinn - während wir heute uns den Freeware-NL202 ansehen und den 3D-Löwen sowie den 3D-Schriftzug bestaunen - und ebenso erstaunt sind, dass das OMSI frisst...
Selbstverständlich ist der NL202 ein gelungenes und natürlich sehr beliebtes OMSI-Addon. Trotzdem bin ich mal so frech und stelle ihn neben unseren in Entwicklung befindlichen NG272:
Was fällt auf? Der NL202 verfügt über wesentlich mehr Polygone als der NG272. Selbstverständlich lassen sich bestimmte Dinge nur darstellen mit entsprechend detaillierten Modellierungen, z.B. die Schrägstellung der Lüftungsschlitze oder das Profil des Fenstergummileisten. Aber man muss sich beim Fahrzeugbau ständig fragen: Brauch ich das wirklich? Lohnt sich einerseits der Aufwand und andererseits der Preis der höheren Polygonzahl? Natürlich sieht es sehr schick aus, aber wann ist man schonmal da hinten am Motorraum?
Denn wenn man von weitem schaut, dann reicht eine passende fotoreale Textur im Allgemeinen aus. Natürlich glänzen unsere Lüftungsschlitze dafür nicht so schön in der Sonne! :)
Vertices nur da einbauen, wo es auch sinnvoll ist
Noch ein Beispiel zum Thema Vertex-Einsparung:
Natürlich ist das mittlere Rohr das schönste! :) Aber dieses hat auch die meisten Polygone. Die Frage ist nun - wie genau spart man Polygone ein und wieviel optische Einbuße bringt es?
In diesem Fall kann man entweder in Längsrichtung oder in Umfangrichtung sparen. Was bringt mehr? Wenn man ungefähr gleiche Vertex- und Face-Zahlen erhalten möchte, dann sehen die Rohre wie gezeigt aus. Links wird in Längsrichtung kein einziges Mal mehr gebrochen, dafür hat der Umfang immer noch 32 Kanten. Rechts dagegen hat das Rohr nur 8 Kanten, dafür konnten alle sieben Brüche (entspricht ebenfalls 32 Ecken entlang des Vollkreises!) beibehalten werden. Offensichtlich die bessere Lösung: Denn den Querschnitt nimmt man nur wahr, wo das Profil endet (Auspuff) oder auf eine andersfarbige Fläche trifft bzw. selbst eine andere Farbe annimmt, während man die Längsrichtung oft sehr direkt sieht, wie auch in diesem Beispiel.
Typische Ähnlichkeit hierzu haben Haltestangen, die bei heutigen Bussen oft schwungvoll gestaltet sind: Auch dort sollte der "Schwung" ausreichend rund sein - dafür kann das Profil ruhig etwas eckiger sein (Acht- oder nur Sechseck).
Um also zum Anfang zurück zu kommen: 1995 hatte der FlightShop-Jumbo-Jet für den Flight Simulator 95 einen achteckigen (!!!) Rumpfquerschnitt! Das sollte man immer bedenken, wenn man 32-eckige Haltestangenprofile konstruiert! :D