Registriert: Mi Nov 30, 2011 21:41 Beiträge: 136 Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
Hallo allerseits,
Ich habe mal ein paar Fragen, naja, eher einige Fragen.
1. Wie teuer ist eine Uniform übergabe? 2. Wenn ich einen Raum mit einigen Lichtquellen habe, ist es dann besser die Wand in Segmente aufzuteilen (mehrere Drawcalls) und dafür kann ich dann bei der Belichtung der einzelnen Segemente sparen (auf jedes Wandsegment wirkt nun ein Teil der Lichtquellen)? 3. Statechanges sind teuer, aber zählt das auch wenn ich nichts binde, also z.B. glBindTexture(GL_TEXTURE_2D, 0) ? 4. Wenn ich eine Wand habe, mit der Länge 1, ist es dann besser, immer alle Wandsegment innerhalb eines Mapteils in ein eigenes VBO zu schreiben, wodurch dann allerdings deutlich mehr VRAM benötigt wird, oder die Wände einzeln rendern? 5. Funktioniert Instancing auch, wenn ich für die einzelnen Objekte unterschiedliche Lichtquellen habe? Also z.B. alle Wandsegmente mit einem Draw-Call rendern, aber für jedes Segment nur die jeweiligen Lichter aktivieren. (Für die Lichter verwende ich Uniforms nicht die openGL lichter)
Notiz am Rande: Die Berechnung welche Lichter überhaupt relevant sind, findet auf der CPU statt und ich habe diese Funktion bereits so gut wie ich konnte optimiert.
Die Hauptfrage ist eigentlich (sollte aus den Einzelnfragen eigentlich klar werden), wie man am besten eine Szene mit vielen Lichtquellen und vielen Objekten rendert.
Die Hauptfrage ist eigentlich (sollte aus den Einzelnfragen eigentlich klar werden), wie man am besten eine Szene mit vielen Lichtquellen und vielen Objekten rendert.
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Knittel hat geschrieben:
1. Wie teuer ist eine Uniform übergabe?
Tja, wie soll man das angeben? Man sollte jedenfalls so wenig API-Aufrufe wie möglich und so viele wie nötig machen. Wenn man in seiner Anwendung VBOs und VAOs verwendet und unnötige Textur- bzw. Statewechsel vermeidet, sind schnell mehr als die Hälfte aller Aufrufe glUniform. Um die Anzahl dieser Aufrufe zu reduzieren, kann man in neueren OpenGL-Versionen Uniform Buffer Objects verwenden - habe ich selbst aber noch nie gemacht. Damit kann man offenbar gleich einen ganzen Satz an Uniform-Variablen auf einen Schlag aktualisieren.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Neu ist relativ... für mich ist alles >= 3.0 "neu", da ich erst in diesem Sommer darauf umgestellt habe.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Weil bisher keins der DGL-Mitglieder einen Artikel dazu verfasst hat. Wenn du das Thema interessant findest und UBOs im praktischen Einsatz benutzt, könntest du ja einen dazu schreiben. Aber jetzt wird's Offtopic.
PS: Und nein, das ist natürlich kein Vorwurf, dass du "nichts machst". Du engagierst dich ja sowieso schon im SDL-Bereich.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
in den nachfolgenden Tuts wird da immer etwas mehr erweitert, Beispielsweise in dem Bereich wo es um das Rendern mehrerer Lichtquellen geht (da lese ich grad rum :p ). Da wird ein UBO verwendet um immer die passenden Materialdaten für ein Objekt zu verwenden.
Registriert: Mi Nov 30, 2011 21:41 Beiträge: 136 Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
Coolcat hat geschrieben:
Zitat:
Die Hauptfrage ist eigentlich (sollte aus den Einzelnfragen eigentlich klar werden), wie man am besten eine Szene mit vielen Lichtquellen und vielen Objekten rendert.
Also ganz so viele Lichter hab ich jetzt nicht^^ Ich habe pro Objekt im Durchschnitt 3 Lichter, weil die Lichter nur einen relativ kleinen Radius haben. Aber halt in der gesamten Szene gut 30 oder 40, Auf der CPU berechne ich welche Lichter für ein Objekt relevant sind und welche nicht, wenn es mehr als GL_MAX_LIGHTS sind, dann werden nur die N relevantesten genommen. Außerdem wollte ich AA benutzen was damit ja dann nicht mehr klappt :/
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Du könntest jedem Objekt einen ivec4 mit auf den Weg geben, in dem die Indizes der relevanten Lichter gespeichert sind. Dann setzt du einmal pro Frame die ganzen Uniform-Variablen für deine 30 Lichter und wählst im Shader aus diesen aus. Das würde sogar mit Instancing funktionieren.
Edit: Wenn die 4 Indices aus dem ivec4 nicht reichen, könntest du natürlich auch zwei ivec4 nehmen. Du kannst aber auch zum Speichersparen mehrere Indizes pro Komponente verpacken. Angenommen, du hast 64 (= 2^6) Lichtquellen, dann brauchst du zu deren Adressierung nur 6 Bit. Du kannst aber davon ausgehen, dass ein int im Shader mindestens 16 Bit hat. Das manuelle zerpflücken im Shader verbraucht aber natürlich wieder einige Zyklen. Da muss man abwägen.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Registriert: Mi Nov 30, 2011 21:41 Beiträge: 136 Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
Ich hab mir mal ein paar Tutorials zu den UBOs angeschaut und das schien auf jeden Fall sehr nützlich zu sein, insbesondere mit der Benutzbarkeit in verschiedenen Shadern. Die Frage ist für mich jetzt noch wie man das genau umsetzt. Sollte ich eher ein einziges UBO wählen und darin alle meine Lichter speichern und dann per ivec4-uniforms (wie von glAwesome vorgeschlagen) die Indizes der relevanten Lichter zu übergeben (Problem: Dann bräuchte ich doch ein dynamisches Array im Shader als Uniform, geht das überhaupt und wenn ja, dann einfach "<variablentyp>[]"? und wie gehe ich vor wenn nur 3 relevante Lichter vorhanden sind? gibts im forloop eines shader einen Break?) oder soll ich für jedes Licht einen einzelnes UBO erstellen (Problem: wie sieht das dann im Shader aus, hab da keine Ahnung wie ich das umsetzen sollte^^)
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Knittel hat geschrieben:
Sollte ich eher ein einziges UBO wählen und darin alle meine Lichter speichern und dann per ivec4-uniforms (wie von glAwesome vorgeschlagen) die Indizes der relevanten Lichter zu übergeben (Problem: Dann bräuchte ich doch ein dynamisches Array im Shader als Uniform, geht das überhaupt und wenn ja, dann einfach "<variablentyp>[]"? und wie gehe ich vor wenn nur 3 relevante Lichter vorhanden sind? gibts im forloop eines shader einen Break?)
Du brauchst kein dynamisches uniform-Array. Ich versuche mal, meine Idee grob zu skizzieren (Fragment-Shader):
Code:
uniform light_t u_Lights[32];
ivec4 LightIDs;// kann uniform oder in sein
// in der main()-Funktion:
for(int i=0; i<4;++i){
if(LightIDs[i]==0)
break;
compute_light(u_Lights[LightIDs[i]-1]);
}
Wenn du nur drei Lichter brauchst, kannst du LightIDs[3] auf 0 setzen und alle anderen Koordinaten belegst du mit dem entsprechenden Index +1.
Die Variable LightIDs kannst du natürlich per Uniform übergeben, was m.E. sinnvoll ist, wenn du sowieso für jedes Objekt eine andere Textur / anderes Material verwendest. Wenn du viele gleiche Objekte renderst, kannst du sie aber auch per Instancing rendern und LightIDs wie hier die Position übergeben. Dann hast du ein VBO, in dem alle LightIDs für jedes Objekt drinstehen.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Registriert: Mi Nov 30, 2011 21:41 Beiträge: 136 Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
ok vielen dank fuer das code beispiel ( dachte an dynamisches array wo du jetzt die 32 stehen hast, für den fall das es in der gesamten szene vielleicht doch mal mehr lichter hat.)
Aber jetzt kann ich mich mal an die umsetzung machen, wenn ich nochmal auf Probleme stoße melde ich mich. Danke nochmal.
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Mir fällt gerade noch eine kleine Optimierungsmöglichkeit ein: Es wäre sinnvoller, wenn du statt der 0 die 32 (oder allgemein eine Zahl, die größer als der größtmögliche Index ist) als Abbruch-Indikator nehmen würdest. Dann kannst du dir das -1 Gerechne sparen.
Statt ivec4 könntest du natürlich auch direkt ein int-Array nehmen. Allerdings benötigst du dann wahrscheinlich 4 mal so viele uniform-Register, weshalb ich das gar nicht erst vorgeschlagen habe. Programmieren ist ein pures Abwägen von Vor- und Nachteilen.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Mitglieder in diesem Forum: 0 Mitglieder und 2 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.