nachdem ich mich Jahrelang vor dem finalen umstieg auf OpenGL 3 und höher im großen maße versteckt habe, brauche ich glaube ich jetzt grad mal ein klein wenig Hilfe..
Meine bisherigen Erfahrungen mit OpenGL 3+ sind alle nur im Bereich von spezifischen visualisern wo ich meine modelView und projection matrix einfach via glUniform an meinen Shader übergeben habe, genauso die Licht Informationen.
Jetzt habe ich bei meiner Engine allerdings weit mehr als nur einen Objekt mit nur einem Shader.. und ich frage mich, was ist der geschickteste weg die Matritzen und Licht infos zu übergeben? Für die Matritzen kann ich mir ja noch irgendwie vorstellen das die für jeden Shader/Objekt via glUniform gesetzt werden, die Licht daten allerdings auch?
Bei OpenGL 2.0 habe ich die glLight* funktionen benutzt und im Shader darauf zugegriffen, musste also auf CPU seite das ganze nur einmal setzen pro Frame.
Gibt es Shader-Übergreifende-Uniform variablen oder so was ähnliches? Andererseits hat man ja am ende millionen von glUniform calls.. oder nicht?
Gibt es Shader-Übergreifende-Uniform variablen oder so was ähnliches? Andererseits hat man ja am ende millionen von glUniform calls.. oder nicht?
Solange, man die Lichposition/Farbe nicht ändert, muss man die Licht-Daten nicht bei jedem Render-Durchgang nei in den Shader schreiben. Bei der Matrix, ist dies natürlich anders, die ändert meistens bei jedem Render-Durchgang.
Vielleicht kann man was mit UBOs etwas machen, aber dort ist die Anzahl stark begrenzt.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ich habe ein UBO für die Matrizen und globales Licht. Das geht ganz gut, auch mit OpenGL 3.3 schon:
Code:
#version 330 core
layout(std140)uniform MatrixBlock {
layout(row_major)mat4 proj;
layout(row_major)mat4 view;
vec4 sun_colour;
vec3 sun_direction;
vec4 sky_colour;
vec3 world_viewpoint;
} mats;
Da kann man natürlich mehr reinpacken. Der Vorteil an row_major ist, dass ich da ganz einfach C++-Matrizen reinkippen kann. std140 wird gebraucht, damit man das Alignment aus C++ heraus berechnen kann und der GLSL-Compiler da nichts wegoptimieren darf. Damit kann man das UBO über mehrere Shader hinweg verwenden. Das ist ganz nett, sodass man die Daten nur einmal zu Beginn des Frames in das UBO kippt.
Details gibt’s im OpenGL-Wiki. Ein bisschen frickelig ist das Berechnen des Alignments, aber auch das ist dokumentiert (für std140 ist eine PDF verlinkt in der die Alignment-Regeln genau drin stehen).
viele Grüße, Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my 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
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2621 Wohnort: Berlin
Programmiersprache: Go, C/C++
In die UBO packt man prinzipiell alles, was über die Shader hinweg geteilt wird und Async sein soll. Ich würde in den UBO ledeglich die Matrizen für die Renderpipeline packen und das licht seperat liefern, da es in der Regel nur im Fragmentshader und auch nicht in jeden gebraucht wird. UBO's werden automatisch über den Bus synchronisiert, wenn der Treiber ein perfekten Punkt sieht oder spätestens, wenn die Daten gebraucht werden. Dieser Unterschied macht die Performance zum alten Update der Daten.
// Alle Nachrichten von den Komponenten verarbeiten(sind Nachrichten die nur auf einem bestimmten Thread laufen können z.B. OpenGL, FMod, Scaleform,...).
Ich übergebe schon die ModelViewProjection Matrix, damit die nicht im Vertex Shader immer wieder aus den einzelnen Matrizen berechnet werden muss. Auf der CPU kostet mich das nur einmal 36 Multiplikationen und auf der GPU wären das für jedes Vertex 36 Multiplikationen und so sind es 12.
Wie Lord Horazont schon erwähnt hat, sollte man drauf achten, das die Lineare Algebra Lib die Matrizen im passenden Format im Speicher ablegt aber beim padding muss mich sich dann eher keine gedanken machen, wenn man nur mit floats arbeitet.
Ich nutze binding slots, da die API viel verständlicher und schneller ist, als es über Namen aufzulösen. Der UBO wird als letztes gebunden, weil ich das im Code sinniger empfand. Erst baut man seine VBO und packt die in ein VAO, da kann man schon die ersten beiden binden und in der Renderloop oder beim erzeugen vom UBO tut man dann das UBO binden.
Man hat selten ein Licht, daher macht es sinn ein VBO/UBO dafür zu haben, je nach wie du dein Licht renderst(forward, forward+, deferred lighting).
Tak, so wie ich deinen Code verstehe setzt du die matritzen nur einmal pro frame, bzw wenn sich die Camera bewegt? Uebergibst du dann die lokale objekt matrix nochmal separat an den shader und multiplizierst diese dann im Shader? Oder missverstehe ich etwas?
Was ist denn aktuall der ideale weg die Licht informationen bei einem normalen Forward renderer an den Shader zu uebergeben? Ein UBO mit vordefinierten platz fuer X lichter und einem extra "numLights" um zu wissen wieviele lichter verwendet werden?
Uebergibst du dann die lokale objekt matrix nochmal separat an den shader und multiplizierst diese dann im Shader? Oder missverstehe ich etwas?
Nein, dieser multipliziert er mit der CPU. Die einte Matrix wird für die Polygon-Berechnung gebraucht (gl_Position). Die zweite, nur für die Lichtberechnung. Normalerweise, müsste mit Modellview noch mit inNormal berechnet werden. Ich denke, in seinem minimal Shader will er nur zeigen, wie die mit den UBOs geht.
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2621 Wohnort: Berlin
Programmiersprache: Go, C/C++
Ja, es ist ein minimalshader, den man für statische world modelle oder instancing nutzen kann. Normalerweise hast du noch eine normale model matrix oder position und quaternion für das positionieren aber das würde ich nicht in ein UBO packen.
Ja ich würde für ein forward renderer auch so vor gehen. Je nach wieviele lichter du hast braucht man Optimierungen, z.b. Die objekte nach den lichtern zu sortieren, damit wenige Änderungen am UBO benötigt werden. Aber erstmal gucken wie weit dich der Vorschlaghammer bringt. Die matrizen per UBO bringen schon ordentlich Performance. Wenn du da einfache 16 lichter oder so hast juckt es die Grafikkarte eher wenig.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Mitglieder in diesem Forum: 0 Mitglieder und 107 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.