als Weiterführung aus diesem Thema: viewtopic.php?f=2&t=9346&start=30 gehts nun um die 3D-Texturen. Musste leider ein kleine Pause einlegen darum gehts jetzt erst weiter. Kurz: Ich möchte mehrere Projektoren (Scheinwerfer) mittels Shadern realisieren. Dazu möchte ich die zu projezierenden Texturen über eine 3D-Textur in den Shader bekommen, damit ich nicht die TMU Begrenzung beachten muss.
Habe leider nicht viel über 3D-Texturen gefunden. Wie bekomme mehrere 2D-Texturen in eine 3D-Textur?
Kurze Frage nebenbei: Kann ich einem Shader ein dynamisches Array (4x4Matrizen) übergeben?
Wie bekomme mehrere 2D-Texturen in eine 3D-Textur?
Ich würde mal glTexImage3D mit GL_TEXTURE_2D_ARRAY als Target vorschlagen. Selbst gemacht habe ich das noch nicht. Bei einer normalen 3D-Textur würde nämlich auch in Z-Richtung linear interpoliert, was ja hier nicht erwünscht ist. Ich glaube das braucht die Extension GL_EXT_texture_array (oder OpenGL 3.0). Im Shader musst du dann auch entsprechend einen Array-Sampler und die Array-Texturzugriffsfunktionen (ab GLSL 1.3, siehe Spec) benutzen.
Zitat:
Kurze Frage nebenbei: Kann ich einem Shader ein dynamisches Array (4x4Matrizen) übergeben?
Du kannst Uniform-Arrays übergeben, diese müssen aber eine konstante Größe haben. Wenn du aber zusätzlich die Größe des Arrays als Uniform übergibst hast du ein dynamisches Array, zumindest in einem gewissen Rahmen. Beachte das die Anzahl der Uniforms begrenzt ist. Für größere Datenmengen eignet sich die Verwendung einer Textur mit einem Float-Format, z.B. GL_RGBA32F_ARB was aber die Extension GL_ARB_texture_float (oder OpenGL 3.0) benötigt. Das ist dann wirklich dynamisch. Besser als Texturen sind für solche Fälle natürlich TBOs, was aber recht aktuelle Hardware erfordert.
Kleines Beispiel: Meine Textur hat jeweils eine Matrix pro Zeile, bei 4 floats pro Texel ist sie also 4 Texel breit. Wichtig ist das der Texturfilter auf GL_NEAREST steht damit nicht zwischen Texel interpoliert wird.
Code:
uniform sampler2D tTextureMatrices; // Textur mit GL_RGBA32F_ARB als internes Format uniform float uTextureMatrices; // Anzahl Matrizen
Eine "Komponente" ist hier ein vec4. Ist meines Wissens aber nicht festgelegt ob z.B. ein Array von vec2 zusammengefasst wird. Ein mat4 braucht natürlich vier vec4, ein mat3 wahrscheinlich drei vec4.
Was passiert denn wenn ich in einem Shader mal mehr als unterstützt deklariert habe, läuft dann der ganze shader nich mehr?
Richtig, dann wird das compilieren des Shader fehlschlagen.
Thmfrnk hat geschrieben:
Gibts denn bei GL_MAX_TEXTURE_IMAGE_UNITS auch einen Mindestsupport?
Laut Spezifikationen: OpenGL 2.1 = 2 (in der Praxis werden es 4-8 sein, habe aber keine Erfahrung da ich für so eine Hardware nicht programmiere) OpenLG 3.0 bis 3.3 = 16
nun aktuell will ich daher gehen und 3 Shader-Varianten schreiben - für ältere mit 2 Samplern für die Projektorbildchen - für das mittelmaß mit 4 Samplern - und für supi Grakas mit 32 Sampler (hat meine z.B.)
Doch ich werde das gefühl nicht los das das ein morts schreibaufwand wird, da ich ja 32 Uniformvariablen deklarieren müsste... und diese könnt ich ja nichtmal in einer schleife ansprechen.. Also brauch ich doch irgendein Arraytyp für die Texturen..
Sampler kann man leider nicht in ein Array packen. Warum habe ich leider auch nicht verstanden, aber aus Sicht der Hardware wird das schon seinen Grund haben. Möglichkeiten: 1. Einfach 32 Uniform-Variablen und ein gigantisches Switch zur Texturabfrage. => Extrem hässlich aber einfachste Variante. 2. Sofern deine Texturen nicht zu groß sind kannst du alle in eine große 2D-Textur packen. Wenn eine Grafikkarte allerdings mehr als 4096x4096 Texturen kann, kann sie wahrscheinlich auch schon 2D-Array-Texturen. 3. Eine 3D-Textur mit GL_NEAREST als Texturfilter und ohne Mipmaps. Du kannst Mipmaps und einen bi- oder trilinearen Texturfilter manuell im Shader implementieren. Funktioniert, ist aber sehr langsam. 4. Kannst du vielleicht eine dem Deferred Shading ähnliche Technik benutzen damit es weniger Overhead ist mehrfach zu rendern? 5. Als Alternative zu 2. kommt möglicherweise eine VirtualTexture/MegaTexture in Frage. Extrem aufwendig zu Implementieren, dafür aber nur geringe Hardwareanforderungen (OpenGL 2.0 mit FBO-Extension reicht), Texturen von 262144 x 262144 sind recht problemlos möglich (*) und das auch noch bei guter Performance. Die Textur ist nur virtuell und liegt nicht vollständig im Grafikspeicher. Eine normale Textur dient als Cache in der 128x128 Texel große Schnipsel der großen Textur gespeichert werden. Im Shader werden die Texturkoordinaten jeweils so umgebogen das sie auf die richtige Stelle im Cache zeigen. In meiner Diplomarbeit will ich mit dieser Technik 80 GB Texturdaten managen die von einem Server auf den Client gestreamt werden. Als Einstieg in die Materie empfehle ich diese Bachelorarbeit von Andreas Neu die bei uns am Lehrstuhl entstanden ist.
(*) 524288 x 524288 und ggf. auch mehr ist ebenfalls möglich, aber dann muss man anfangen zu tricksen, da die Genauigkeit eines 32bit Floats am Ende ist.
ich versuche für den Anfang mal die 1. Variante.. doch mir ist gerade aufgefallen ich kann ja ein Sampler nur übergeben in dem ich eine Texturunit wähle (glActiveTextureARB(GL_TEXTURE1)), da eine Textur binde und diese dann mittels glUniform1iARB an den jeweiligen Sampler schicke..
Nun so kann ich doch maximal nur so viele Sampler nutzen wie ich TMUs (GL_MAX_TEXTURE_UNITS_ARB) habe ode? Denn da hab ich nur 4.. im Shader 32..
Oder hab ich da jetzt einen denkfehler..
hatte gedacht das geht so: - setzte TMU1 - Binde Projektionstextur1 - Setze Sampler für Shader auf 1 - Binde Projektionstextur2 - Setze Sampler für Shader auf 1..
hatte gedacht das er die an den Shader übergebene Textur irgendwo zwischenspeichert..
GL_MAX_TEXTURE_UNITS bezieht sich wahrscheinlich auf die FixedFunctionPipeline. => GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS (TMUs im Vertexshader) GL_MAX_TEXTURE_IMAGE_UNITS (TMUs im Fragmentshader, glaub ich jedenfalls) GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (TMUs gleichzeitig in Vertex- und Fragmentshader)
Am besten schaust du selbst nochmal in die Spec wofür die Werte genau stehen. Ich hab jetzt nur geschaut was mir "glxinfo -l" sagt.
Zitat:
hatte gedacht das er die an den Shader übergebene Textur irgendwo zwischenspeichert..
Über glUniform1i setzt du direkt die Nummer der Texturunit. Es reicht übrigens auch das einmal zu setzen nachdem du den Shader compiliert&gelinkt hast. Erst zu dem Zeitpunkt an dem du renderst muss da auch wirklich eine Textur auf der entsprechenden TMU gebunden sein.
Was verstehst du unter "texturen einzeln übergeben"? Wenn du Shader benutzt kannst du mit glActiveTexture halt bis GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS gehen statt nur bis GL_MAX_TEXTURE_UNITS.
Mitglieder in diesem Forum: 0 Mitglieder und 14 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.