Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jun 20, 2025 23:06

Foren-Übersicht » Programmierung » OpenGL
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 14 Beiträge ] 
Autor Nachricht
BeitragVerfasst: So Apr 08, 2012 10:18 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 03, 2007 14:22
Beiträge: 388
Moin,

erstmal Frohe Ostern.

Ich bin auf eine Fragestellung getroffen, welche mich irgendwie schwer beschäftigt, da sie so grundlegend ist, ich dazu jedoch keine guten Wege finde.

Machen wir es möglichst simpel, das entspricht auch fast der Fragestellung dann:
Stellt Euch ein Feld vor, der Einfachheit halber ist es komplett leer, sprich einfach ein Quadrat. Auf dieses Quadrat (könnte auch Rechteck sein, aber Quadrat tut genauso) werden zufällig viele kleine Würfel gezeichnet. Das heißt das Feld wird in ganz viele (>50000) kleine Felder unterteilt und je nach Zufall werden mehr oder weniger viele davon mit einem Würfel belegt. Die Würfel füllen aber nicht das gesamte Feld aus, es grenzen also keine Würfel direkt aneinander. Außerdem können Würfel unterschiedlich hoch sein und die Würfel lassen sich auch durch Zylinder oder Kugeln ersetzen wenn man will. Die gesamte Szene ist statisch, die Würfel bleiben wie sie sind.

Nun gibt es zwei Fälle:
1. Man befindet sich mit der Kamera irgendwo am Boden und hat daher ein schwer begrenztes Sichtfeld, man kann also via Frustum oder so ermitteln, welche Würfel überhaupt sichtbar sind und diese dann zeichnen.
2. Man befindet sich mit der Kamera genau so dass man alle Würfel sehen kann.

Der erste Fall dürfte keine Probleme machen, da man nur ein paar der ganzen Würfel überhaupt berücksichtigen muss. Der zweite Fall ist jedoch ein Performance-Killer scheinbar. Ich habe das auch mal schnell getestet und es ruckelt wirklich übel. Dann habe ich eine DisplayList verwendet welche alle Würfel drinnen hat - das optimiert ein wenig, aber es ruckelt immer noch ganz gut und mit älteren Grafikkarten wäre es der Horror (mal abgesehen davon dass meine pfeift dabei...). Ich habe verschiedene Methoden überlegt, wie man das lösen könnte. Da die Objekte statisch sind, ist die DisplayList soweit ich es sehe einem VBO vorzuziehen. Ich bin hier wirklich ein wenig mit meinem Latein am Ende, weil es ja eine Lösung geben muss, um viele Objekte zu zeichnen. Das was ich hier zeichne sind absolut einfache Objekte und die Performance kracht schon ein.

Was ich noch gelesen hatte war Instancing, also mal schnell den guten Wiki-Artikel hier aufgemacht und gleich eine Frage: Bringt das viel ? Ich meine Instancing+Shader dürfte grob gepeilt recht gut laufen. Da ich Instancing noch gar nicht kannte, bin ich mir nicht sicher, aber so wie ich es sehe geht das eh nicht oder ? Weil die Würfel sind ja durchaus unterschiedlich. Und hier wird es vielleicht sinnvoller die Frage von den Würfeln weg mal zu verallgemeinern:
Das mit Würfeln ist wirklich Minimalvorstellung, weil man da die Probleme simpel sieht. Meine wesentliches Ziel ist eben wirklich die Beantwortung der Frage, wie man zum Beispiel in einem Flugsimulator mit dem Fall fertig wird, dass das Flugzeug von außen sichtbar so auf eine große Stadt zufliegt, dass die gesamte Stadt im Sichtfeld liegt. Die eigentliche Frage wäre, wie man viele Objekte performant zeichnet, aber ich denke das mit dem Flugzeug oder den Würfeln ist anschaulicher. Wenn diese theoretischen Probleme geklärt sind, will ich das mal auch mit den Würfeln testen, um meine OpenGL-Fähigkeiten mal auf Vordermann zu bringen - also nur Theorie ist das hier auch wieder nicht, aber der Praxisteil ist wirklich das absolute Minimum, da nur Würfel zum Einsatz kommen.

Gruß,
Nils

_________________
Meine Musik: spiker-music.net


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 08, 2012 13:32 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Als generellen Ratschlag verweise ich mal auf unseren Performance-Artikel im Wiki um die groben Fehler auszuschließen.

Folgende Infos sind in deinem Fall entscheidend:
- haben deine Würfel eine Textur? Wenn ja ist diese für alle Würfel gleich oder gibt es mehrere?
- die Würfel/Zylinder/Kugeln unterscheiden sich ausschließlich durch ihre Position, Skalierung und ggf. Vertexfarbe? (keine Rotation etc.?)
- wie renderst du die Szene innerhalb deiner Displaylist? Ich hoffe alles ist in einem einzigen glBegin/glEnd, oder?

Zitat:
Da die Objekte statisch sind, ist die DisplayList soweit ich es sehe einem VBO vorzuziehen.

Ich persönlich bevorzuge VBOs, da man dort mehr Kontrolle darüber hat was eigentlich genau passiert. Die Performance ist bei richtiger Anwendung ähnlich. Der Unterschied ist das man bei einer Displaylist davon abhängig ist das der OpenGL-Treiber schlau genug ist das zu optimieren. Von Hand geht das wesentlich besser, weil man einfach viel mehr Infos hat was man da eigentlich treibt als der Treiber jemals orakeln könnte.


Im Falle der ganzen Stadt die man vom Flugzeug aussieht ist LevelOfDetail (LOD) das Stichwort. Du renderst die entfernten Objekte nicht in voller Qualität. Die Schwierigkeit ist den Übergang zwischen den LOD-Stufen zu vertuschen.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 08, 2012 21:04 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 03, 2007 14:22
Beiträge: 388
Performance-Artikel hatte ich im Hinterkopf, werde es jedoch nochmal richtig überprüfen.

Die Würfel/Zylinder/Kugeln haben eine Textur. Sie unterscheiden sich durch Position, Skalierung, Textur und leider werden auch manche Würfel rotiert sein.
Verdammt, das ist der Nachteil wenn man sich über Jahre hinweg Units schreibt und nur mal schnell eine Funktion zum Zeichnen eines Würfel nimmt, ohne sie nochmal richtig durchzulesen. Ich habe die glBegin/glEnd rausgenommen und drumherum gepackt, es ruckelt nichts mehr, ist auch logisch dass das eine üble Performance-Bremse war.

Welche Form von LOD-Berechnungen wären für so etwas wie das Würfel-Beispiel am ehesten geeignet ? Zu VIPMs steht was im Wiki, zu den anderen hier vorgestellten Methoden steht leider nichts im Wiki.

Zu VBOs: Als Lernziel werde ich VBOs auch mal antesten demnächst, habe damit noch nichts gemacht und muss erstmal dann schauen, was genau richtige Anwendung meint - DisplayListen kenne ich hingegen halt schon ewig und sie sind ja leicht zu bedienen, aber gerade was Du mit den Optimierungen da schreibst klingt sehr überzeugend VBOs zu nehmen.

_________________
Meine Musik: spiker-music.net


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Apr 09, 2012 09:08 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Welche Form von LOD-Berechnungen wären für so etwas wie das Würfel-Beispiel am ehesten geeignet ?

Bei einem simplen Würfel macht LOD nicht viel Sinn. Sehr wohl aber bei einer Kugel bzw. einem Zylinder. Wenn du beim Zylinder einfach in der Entfernung etwa nur 6 statt 30 Ecken benutzt reduzierst du die Anzahl der Dreiecke massiv ohne das es groß auffällt.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Apr 09, 2012 13:06 
Offline
DGL Member
Benutzeravatar

Registriert: Di Sep 06, 2005 18:34
Beiträge: 362
Wohnort: Hamburg
Hi,

Bei so vielen gleichartigen Objekten würde mich aber schon interessieren ob man mit Instancing da überhaupt so viel raus kitzeln kann.
Ich frage mich ob die Mehrarbeit, die der Shader da leisten muss, wirklich noch so viel Performance bringt.

Wenn ich das richtig mitbekommen habe, unterscheiden sich deine Würfel durch diese Dinge:
- Textur
- Position
- Skalierung/Rotation
Ich würde nach Textur/Material sortieren und für jede Gruppe einen Draw-Call machen. D.h. du bindest die entsprechende Textur und renderst dann die Objekte.
Du musst dir nur noch überlegen wie du die anderen Informationen in den Shader bekommst. Ich würde ein TextureBufferObject empfehlen. Wird quasi benutzt wie ein VBO, nur dass du direkt auf die Daten aus dem Shader zugreifen kannst wie auf eine 1D-Textur. Da musst du dir also ein Format überlegen, wie du die gewünschten Informationen dort unter bekommst. Dieses TBO kannst du dann im Shader binden um mit Hilfe der gl_InstanceID heraus zu bekommen wie genau du die aktuelle Instanz nun rendern musst (also alle transformationen durchführen).

Man könnte auch alle Objekte in einem Rutsch zeichnen wenn man alle Texturen bindet und die zu benutzende Texture Unit auch im TBO ablegt, ich glaube aber nicht, dass das sinnvoll ist, da man da sicher je nach Scene in irgendeinen Konflikt mit Hardware Beschränkungen kommt.

_________________
Der Mensch hat neben dem Trieb der Fortpflanzung und dem zu essen und zu trinken zwei Leidenschaften: Krach zu machen und nicht zuzuhören. (Kurt Tucholsky)
Schwabbeldiwapp, hier kommt die Grütze. (Der Quästor)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Apr 09, 2012 14:23 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Bei so vielen gleichartigen Objekten würde mich aber schon interessieren ob man mit Instancing da überhaupt so viel raus kitzeln kann.

Instancing bringt vollem dann viel wenn die Objekte dynamisch, d.h. wenn sich ihre Parameter ändern so das man normalerweise den ganzen VBO neu schreiben müsste. Verwendet man Instancing reicht es einfach den TBO mit Parametern neu zu schreiben was die veränderliche Datenmenge massiv reduziert.

Des weiteren kann man sich Cache-Effekte zu nutze machen da immer der gleiche kleine VBO benutzt werden kann. Bringt in diesem Fall wahrscheinlich eher wenig.

=> Solange die Szene statisch ist macht Instancing hier im Vergleich zum Implementierungsaufwand wenig Sinn.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 02, 2012 21:17 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 03, 2007 14:22
Beiträge: 388
So, das Thema begann ich ungünstigerweise direkt vor dem Semester, ich hole es daher mal wieder raus, denn das Thema ist genau das gleiche, das erleichtert später die Suche, falls jemand was hierzu sucht.

Habe den Zylinder mal angefangen und an sich läuft die Routine auch. Das große Problem ist, dass ich keine wirkliche Chance sehe die glBegin und glEnd da rauszukriegen, denn die sind teuer. Level-of-Detail lässt sich ausarbeiten, prinzipiell ist wenigstens klar wie man es regeln müsste. Aber eben, erstmal ist der folgende Code nicht schön, habt Ihr spontane Optimierungseinfälle ?
Dazu kommt natürlich noch dass ich generell nachgedacht habe. Für den Fall dass man alles sieht, bleibt abgesehen von Level-of-Detail nicht viel übrig, aber wenn man nah ran geht, sich in einem großen Feld aus sagen wir Würfeln und Zylindern also insbesondere die Zylinder genauer anschaut, dann ruckelt das schon. Die Würfel sind da nicht so anfällig, aber die Zylinder leider schon, dafür genügt schon ein einziger mit der gezeigten Routine, an den man nur nah genug rangehen muss. Und das zu optimieren ist ja gerade die Ausgangsstellung dieses Themas. Da man in so einer "Landschaft" voller Würfel und Zylinder viele gar nicht sieht, ist rein für den Fall denke ich eine Sichtbarkeitsüberprüfung sinnvoll, dies würde die Performance-Probleme, zumindest wenn man nah dran ist, erheblich abschwächen oder sogar lösen.

Wenn ich die Texturen der Objekte verändere, also die der Würfel und Zylinder, dann wäre Instancing so wie ich es verstehe nicht verkehrt oder - die Objekte bleiben gleich, nur die Texturen können geändert werden ? Ich will halt auch gerne mit größerem Aufwand, aber eben so dass es dann keine Probleme mehr gibt, sich der Aufwand also gelohnt hat, die Performance optimieren. Welche Methoden wären hier ratsam um überhaupt zu überprüfen, was im Sichtfeld liegt ? Frustum Culling ohne Shader etc. schwebt mir noch im Hinterkopf, aber das war aus den Zeiten in denen ich mit OpenGL angefangen habe, gibt es mittlerweile bessere Lösungen ? Generell wird später ein großer Teil der Objekte eher verdeckt sein, aber es könnte dennoch an wenigen Stellen auftreten, dass man alle Objekte auf einmal sehen kann - das ist das eigentliche Problem. Selbst wenn man Algorithmen eigentlich so optimiert, dass der schlimmste Fall akzeptabel wird, halte ich das mit der Sichtbarkeitsüberprüfung trotzdem nicht für unwichtig, weil es generell sicher eine gute Optimierung ist. Habt Ihr irgendwelche Tipps, wie man das geschickt angehen kann ?

Hier noch der Zylinder-Code:
Code:
  1. procedure DrawCylinderIt(Detail : Integer);
  2. var a, d : Real;
  3.     i    : Integer;
  4. begin
  5.   d := 2*PI/Detail;
  6.   glBegin(GL_TRIANGLE_FAN);
  7.   glVertex3f(0.0, 0.0, 0.0);
  8.   a := d;
  9.   for i := 0 to Pred(Detail) do
  10.   begin
  11.     glVertex3f(Cos(a), Sin(a), 0.0);
  12.     a := a+d;
  13.   end;
  14.   glEnd;
  15.  
  16.   glBegin(GL_TRIANGLE_FAN);
  17.   glVertex3f(0.0, 0.0, 1.0);
  18.   a := d;
  19.   for i := 0 to Pred(Detail) do
  20.   begin
  21.     glVertex3f(Cos(a), Sin(a), 1.0);
  22.     a := a+d;
  23.   end;
  24.   glEnd;
  25.  
  26.   glBegin(GL_TRIANGLE_FAN);
  27.   a := d;
  28.   for i := 0 to Pred(Detail) do
  29.   begin
  30.     glVertex3f(Cos(a), Sin(a), 0.0);
  31.     glVertex3f(Cos(a), Sin(a), 1.0);
  32.     a := a+d;
  33.   end;
  34.   glEnd;
  35. end;

_________________
Meine Musik: spiker-music.net


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 02, 2012 23:06 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
TRIANGLE_FAN nutze ich nie. Da verschwende ich lieber ein paar Vertices und bauen das Objekt aus normalen Dreiecken auf.
Erleichtert auch den evtl. Umstieg auf VBOs und macht auch das verarbeiten und speichern in Arrays einfacher. Sonst muss man wieder jede Menge IFs einbauen um jeden denkbaren TRIANGLE Typ zu unterstützen. Baue nen Zylinder auch lieber in Blender und lade den dann einfach...

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 03, 2012 07:03 
Offline
DGL Member

Registriert: Mi Okt 16, 2002 15:06
Beiträge: 1012
Betreffend Instancing...

ich habe das mal vor Monaten ausprobiert, als ich eine Performante-Methode gesucht habe, 256.000 Partikel in Echtzeit zu rendern, wo in jedem frame für jeden Partikel die Position bestimmt wird.

Logischerweise war das eine Ruckelorgie, wenn ich für jeden Partikel eine Sphere rendere.
Danach habe ich das ganze auf TBO´s mit Instancing umgestellt und es war deutlichst schneller aber für mich noch nicht schnell genug.

Am ende habe ich es so gemacht, das ich nur noch Punkte/Point-Sprites Rendere anstatt Geometrie und im Shader die Sphere selbst berechne. Für Spheres funktioniert das hervorranged, ebenfalls mit Beleuchtung und so :)

Für dich wäre aber die TBO Lösung eindeutig besser, da kannst du einiges rausholen sofern du nicht 50.000 unterschiedliche Objekte hast.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 03, 2012 21:19 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Nils, bevor du mit komplexen Dingen wie Instancing anfängst, optimieren zunächst erst mal deine Zeichenmethode. glBegin/glEnd ist tödlich, insbesondere, wenn du da drei Draw-Calls pro Zylinder produzierst. Deine Vertices die du da produzierst hängen nur vom Parameter "Detail" ab, du kannst also wunderbar für jede gewünschte Detailstufe einmal einen VBO erzeugen. Benutze GL_TRIANGLES.

Vor dem Rendern stellst du eine Liste der sichtbaren Zylinder zusammen (FrustumCulling). Bei der Gelegenheit berechnest du auch gleich die nötige Detailstufe, die Liste enthält also im wesentlichen Position & Ausrichtung des Zylinders und die Detailstufe. Die Liste sortierst du nun einfach nach der Detailstufe, von vorne nach hinten.

Zum rendern gehst du nun diese Liste durch:
Code:
  1. 1. VBO für aktuelle Detailstufe binden
  2. 2. Alle Zylinder dieser Stufe rendern
  3. 3. Nächste Detailstufe, weiter bei 1.



Wenn du weiter optimieren willst, nutze einen Indexbuffer (auch "Elementbuffer").



P.S. Frustum-Culling hat nichts mit Shadern zu tun, das passiert bevor die Daten auf der Grafikkarte ankommen. Wenn der Shader angeworfen wird ist es eh schon zu spät.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Aug 04, 2012 11:20 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Es sind halt viele Faktoren und daher tut man üblicherweise profilen http://www.gremedy.com/, http://www.nvidia.de/object/nsight-de.html, http://www.nvidia.de/object/nvperfkit_home.html .
Sobald man dann in bunt sieht, wo der Flaschenhals ist geht man geziel gegen vor.
Was wir gemacht haben ist einfach aus gesammelter Erfahrung geschätzt, wo die Flaschenhälse auftreten aber heute ist das so eine Sache, zu viele Grafikkarten, mit zu unterschiedlichen Treibern, in zu unterschiedlichen Systemen können schnell zu falschen Vermutungen führen.

Ich vermute, dass es die anzahl der calls ist, die mit dem treiber und gpu reden müssen.
Ist dies der Fall, dann gibt es diverse Lösungen.
Reduzierung der bind Befehle, durch zusammen legen mehrerer Ressourcen in eine(meshes, texturen).
Reduzierung der Rendercalls durch instancing, verlagerung von LOD auf die GPU oder ganz drauf verzichten.

Ist es die Füllrate, dann ein Z-Pass einbauen, wenn noch nicht passiert.
Shader vereinfachen(instructions zählen und durch günstigere ersetzten).
Prüfen ob die MipMaps für Texturen generiert wurden(wenn nicht, dann unbeding machen, ausser welche die nur in 2d mode genutzt werden).

Ist es die Vertexrate, dann weniger Objekte zeichnen, meshes vereinfachen, lod, tesselierung oder imposter verwenden.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Aug 04, 2012 21:15 
Offline
DGL Member

Registriert: Mi Okt 16, 2002 15:06
Beiträge: 1012
Ich kann gDEbugger wärmstens empfehlen. Das programm ist der Traum für OpenGL Entwickler, weil es einem erheblich hilft Fehler zu finden, oder seine Anwendung zu optimieren. Alleine schon die tatsache dass man sich jede x-beliebige texture anschauen kann ist gold wert, so habe ich viele Fehler schon im vor feld sehen können. War extremst hilfreich, bei der Entwicklung meiner Realtime Fluid-Simulation weil ich ja da nur noch mit etwailigen FBO Targets zu tun habe.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Aug 06, 2012 15:58 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 03, 2007 14:22
Beiträge: 388
Habe alle Eure Vorschläge längst gelesen und mir dann recht schnell überlegt, dass es wohl sinnvoller ist, wenn ich ein paar Baustellen zunächst beseitige um dann erstmal einen genaueren Überblick zu bekommen, was genau das Problem sein wird. Mit Frustum Culling und solchen Sachen holt man halt auch nur begrenzt was raus und ich wollte einiges erst implementiert und angeschaut haben um dann mit Euch besser darüber reden zu können. Ist ein langer Beitrag, in der Hoffnung alle Probleme und Überlegungen möglichst klar dazustellen, alles andere hat glaube ich keinen Sinn.

Im Anhang sind zwei Screenshots. Der linke dient eigentlich nur dazu, um überhaupt zu sehen, was das sein soll, denn es ergibt sich nur ein hässlicher Klumpen im rechten Bild, der sonstwas sein könnte. Die ganze Szene ist zufällig erstellt worden. Ich habe also generell das Terrain im Speicher und habe das Terrain aufgeteilt in 8x8 große Felder, welche dann ein Gebäude zugeordnet bekommen, wobei ich für jedes Feld speichere ob es überhaupt belegt ist, welches Gebäude (eigener Record) drauf ist und noch viel mehr. Das Gebäude wiederum hat dann wenig Infos gespeichert zur Zeit, nennenswert festgelegt ist bisher nur die Gesamthöhe, der Rest ist Kleinkram den keinen an dieser Stelle hier interessiert.
Mein eigentliches Ziel ist es, eine simple Stadt aufzubauen, die nur aus Hochhäusern besteht - alles andere interessiert erstmal nicht bis die Performance gut genug ist. Da gibt es nun verschiedene Ansätze und gerade in den letzten Posts hier kam gut raus, dass die Optimierungen doch schwer vom Einzelfall abhängen.
Zur Zeit werden die Daten des jeweiligen Hochhauses sowie die gesamte Spielkarte bis auf das Terrain wieder direkt aus dem Speicher gelöscht, da die Informationen später nicht mehr benötigt werden. Klar, es wäre cool wenn Licht an Fenstern nicht nur statisch wäre sondern sich hin und wieder mal ändern würde, aber das ist Schnick-Schnack und solche Sachen lasse ich vollkommen außen vor erstmal. Daher war die allgemeine Überlegung erstmal möglichst viel Speicher zu sparen. Jedes Hochhaus ist zur Zeit nichts weiter als ein Stapel von Quadern oder Zylindern, wobei jeder Quader oder Zylinder immer ein wenig schmaler ist als der unten drunter. Eine Prozedur klatscht mir das zusammen, wobei dann das gesamte Hochhaus direkt in einer Displaylist landet. Displaylist ganz einfach weil es in fünf Sekunden schon implementiert war und man solche Optimierungen natürlich gerne mal gratis mitnimmt. VBO müsste ich mich erst genauer reinlesen, was ich noch tun werde, aber ich wollte selbst erstmal die grundsätzlichen Probleme herausfinden und da bringt mir ein VBO erstmal auch nichts bei. Ich habe also für jedes Gebäude im Ganzen eine eigene Displaylist.
Analysiert man ein Quader-Hochhaus, so fällt direkt auf, dass sich das suboptimal, aber schnell, als einziger Quader auffassen lässt, nämlich mit der Grundfläche als Grundfläche und der Gesamthöhe als Höhe (klingt komisch, stimmt aber so). Die Hochhäuser werden nach oben hin schmaler deshalb ist das ein wenig suboptimal. der Frustum-Test geht aber flott und bringt auch schon mal was - aber eben nicht immer, weshalb es als Lösung noch nicht reicht.
Zylinder-Hochhaus funktioniert genauso und lässt sich ebenfalls als Quader annähern. Zu erwähnen ist, dass ich - wieder der Einfachheit halber - zwei Displaylisten habe mit unterschiedlichen Detailstufen der Zylinder-Hochhäuser. Der Kugel-Test ist in meinen Augen so wie im Frustum Culling-Tutorial nicht anwendbar, ansonsten wäre das natürlich schneller, geht hier aber wohl nicht, da ein Hochhaus dann eine immense Kugel erzeugen würde, die anschaulich gesprochen viel zu "breit" wäre.

Soweit dazu erstmal. Der nächste Design-Schritt ist eben das Ausknipsen vom Licht und Erzeugen von Atmosphäre mit Lichtern aus den Hochhäuser-Fenstern sowie das Beseitigen dieser fehlenden Detailkraft, man sieht ja die Hochhäuser von der Ferne kaum (wie später erklärt setze ich zur Performance-Optimierung momentan keine Normalen, daher sieht es so mies aus). Problem dabei ist, dass es doof aussieht, wenn jedes Hochhaus gleiches Licht hat, daher bin ich die ganze Zeit auch auf veränderliche Texturen oder direkt Shader aus, denn ich sehe keine andere Chance das gescheit hinzukriegen. Der Vorteil beim Abstellen vom eigentlichen Licht ist übrigens, dass Späße wie Schattenberechnung (bei vielen Hochhäusern wäre das sehr langsam denke ich) wohl entfallen können - falls man später spezielle Schatten braucht, kann man die ja noch einbauen. Ich will an dem Projekt viel lernen und daher ist gerade der Realismus hier sehr interessant, ich will einfach mal wissen, wie man so etwas macht, weil algorithmisch so ein paar Hochhäuser zu erstellen geht recht leicht, aber eben nicht sie gut darzustellen.

Oben wurden VBOs für einzelne Detailstufen angesprochen, welche nach Detailstufe sortiert und gerendet werden. Wenn man so viele Würfel oder Zylinder aufeinander baut, dann weiß ich nicht ob das gut ist es so zu machen: Es gibt ein VBO für die jeweiligen Detailstufen in Einheitsform, sprich alle Längen im VBO sind stets 1 sodass ich leicht später skalieren kann. Dann skaliere ich mir während dem Zeichnen alles schön hin und schiebe alles so hin wie es passt. Das sind einige Matrixoperationen die ich mit obiger Variante nicht brauche, nach obiger Variante zeichne ich sämtliche Würfel/Zylinder ohne ein einziges glTranslate/glRotate/glScale, da ich direkt alles an den richtigen Ort zeichne - ich habe übrigens auch alles auf GL_TRIANGLES umgestellt, deutlich flotter, weiß nicht wieso ich nicht selbst darauf kam. Das ist eine Überlegung und ich bin mir nicht sicher was hier schneller ist, meine Methode oben mit so monströsen Displaylisten ist zumindest nicht sehr speicherfreundlich und gerade wegen der Größe der Displaylist eventuell auch langsamer - was hier am schnellsten ist weiß ich aber wirklich nicht, daher kann ich nur fragen.
Abgesehen davon aber gibt es aber ein Designproblem: Während ich in die Displaylisten zeichne, baue ich mir die Blöcke mit zufälligen Höhen aufeinander und speichere mir ihre Größen gar nicht, weil ich sie nie wieder verändern will und eben die Displaylist das Hochhaus schon fertig enthält dann. Bei der Generierung eines Hochhauses mittels dieser VBO-Variante müsste ich also für jeden Block seine Höhe, Breite, Position speichern oder besser gleich alles so, dass glScale und der Rest mit den Werten als Parameter direkt angewendet werden können. Das kostet viel Speicher der nicht freigegeben werden kann, da diese Daten während jedem Render-Vorgang wieder benötigt werden. Sind aber wirklich rein theoretische Überlegungen, ich hatte bloß zeitweise während der Generierung bei 2048x2048 schon ungefähr 185MB Speicher belegt, was mir halt recht viel vorkam für die "paar" Hochhäuser samt Terrain.

Gut und warum schreibe ich das alles, klar: Die Screenshots zeigen ein 512x512 großes Terrain, das ist eigentlich gar nicht so groß. Bei der Größe ruckelt nichts, aber bei 2048x2048 schon ordentlich, 1024x1024 auch schon spürbar. Ich setze keine Normalen, denn dann geht die Performance noch weiter in die Knie, gerade bei 2048x2048 ist das direkt spürbar. Dank Frustum Culling geht es ohne Normalen meist ganz gut, hin und wieder ruckelt es bei größeren Feldern als 512x512 aber schon ganz nett, weil manchmal eben alles sichtbar ist.
Was ich zur Zeit nicht berücksichtige ist das Terrain selbst, denn wenn ich vor einem Berg stehe, sehe ich nur wenig oder gar nichts von dem was dahinter ist, wenn ich was sehe, dann eher die Spitze eines Hochhauses und dann müsste ich nur die Spitze des Hochhauses zeichnen, das erschwert wiederum den Sichtbarkeitstest erheblich, ich müsste für jeden einzelnen Block eines jeden Hochhauses prüfen ob er sichtbar ist und dabei noch zusätzlich eben so Gegebenheiten wie Berge mit einbeziehen (denke das ist am rechenintensivsten). Wenn man 6 Blöcke pro Hochhaus im Schnitt annimmt, wäre das der 6fache Aufwand beim Frustum Culling. Lohnt sich das überhaupt ? Im Extremfall stehe ich auf einem Berg am Rand der Karte und sehe alles, das heißt die Sichtbarkeits-Optimierung bringt dann schnell nichts mehr und es ruckelt.

Ich fordere das Problem hier in gewisser Weise direkt heraus, man könnte auch direkt ein Modell bauen und gut ist, aber mir geht es ja gerade darum dass in OpenGL zu machen, weil ich was lernen will und mal frei experimentieren will (das geht bei diesem Projekt hier wirklich mal gut, macht echt Spaß) :).


Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

_________________
Meine Musik: spiker-music.net


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Aug 06, 2012 17:54 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Das erinnert mich an etwas anderes: Procedural City. Möglich ist das auf jeden Fall.

Ich habe deinen Post nur überflogen, aber ich habe ja auch mal mit großen Terrains gearbeitet. Dabei hat sich Optimierung des Terrains als unglaublich wirksam rausgestellt. Außerdem Sichtbereichsbegrenzung. Ich habe das Terrain dann in 64×64 Chunks aufgeteilt und immer nur die dem Betrachter am nächsten liegenden gerendert, da in meinem Szenario auch ein seichter Nebel vorkam.

Auf diesem Screenshot kann man das optimieren von glatten Flächen schon recht gut sehen. Man braucht halt nicht so viele Triangles um eine Fläche mit wenig Änderung in der Steigung zu rendern (dazu haben wir glaube ich auch was im Terrain-Tutorial 3).

Ebenso würde ich auch die Gebäude für so ein 64×64 chunk in ein VBO zusammenlegen, um teure Drawcalls zu sparen.

grüße

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 14 Beiträge ] 
Foren-Übersicht » Programmierung » OpenGL


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 16 Queries | GZIP : On ]