Erstellen eines GLSL-Arrays von Uniformen?

74

Ich möchte die Lichter von OpenGL verlassen und meine eigenen machen. Ich möchte, dass meine Shader eine variable Anzahl von Lichtern zulassen.

Können wir eine Reihe von Uniformen in GLSL-Shadern deklarieren? Wenn ja, wie würden wir die Werte dieser Uniformen festlegen?

Meilen
quelle
4
Jeder, der eine variable Anzahl von Lichtern möchte, erstellt einfach Arrays mit angemessenen Kapazitäten und zählt, wie viele Lichter derzeit aktiv sind. GLSL erlaubt keine Arrays mit variabler Größe (alle Arraygrößen müssen konstante, fest codierte Werte sein).
Meilen

Antworten:

98

Ja das ist möglich. Sie deklarieren einheitliche Arrays ähnlich wie in C, z

uniform float v[10];

Dann können Sie ihre Werte mit einstellen glUniform{1,2,3,4}{f,i}v

GLfloat v[10] = {...};
glUniform1fv(glGetUniformLocation(program, "v"), 10, v);
Datenwolf
quelle
2
Worauf bezieht sich die 1, 2, 3, 4? Bedeutet das, dass ich nur die Werte eines Arrays auf bis zu vier Mitglieder festlegen kann?
Meilen
Das ist eine sehr clevere / verdrehte Verwendung von glUniform1fv. Man würde denken, dass der 2. Parameter von glUniform1fvnur eine Formalität ist und dass er immer als 1.
Bobobobo
Technisch gesehen könnten Sie ein einheitliches Set vec4mit glUniform1fv( uniformId, 4, v ) ;dem veine Anordnung von vier Schwimmern ist.
Bobobobo
14
@bobobobo: " Technisch gesehen könnten Sie mit glUniform1fv (uniformId, 4, v) ein einheitliches vec4 festlegen. Dabei ist v ein Array von 4 Floats. " Nein, das können Sie nicht. Die Spezifikation ist sehr klar: Die Größe und der Typ müssen mit der Größe und dem Typ der Uniform übereinstimmen (mit Ausnahme der verwendeten iBools und der verwendeten Opake 1i). Wenn Sie sagen 1f, dann muss die Uniform 1 Schwimmer sein. Ansonsten GL_INVALID_OPERATIONfolgt.
Nicol Bolas
9
@ MilesRufat-Latre {1234}in Funktionen wie glUniformerzählt über den Typ der einheitlichen Variablen. 1f bedeutet einen einzelnen Schwimmer, 2i bedeutet ivec2 und so weiter. Dies sollte nicht mit dem zweiten countParameter verwechselt werden, den die Funktion annimmt, nämlich der Arraygröße. Zum Hochladen uniform vec2 vecs[5];wäre es also soglUniform2fv(loc, 5, data); .
Legends2k
6

Ja, es ist möglich, eine Reihe von Uniformen in GLSL-Shadern zu deklarieren. Google einfach "glsl uniform array" für einige Beispiele (edit: oder siehe datenwolfs Beispiel). Es gibt jedoch Einschränkungen, wie viele Uniformen an verschiedene Grafikkarten gesendet werden können (zumindest bei älteren bin ich mir bei den aktuellen nicht sicher (obwohl ich mir das noch vorstelle)).

Wenn Sie sich für Uniformen entscheiden, würde ich die Verwendung von Uniformpuffern vorschlagen. Laut http://www.opengl.org/wiki/Uniform_Buffer_Object ist "das Umschalten zwischen einheitlichen Pufferbindungen normalerweise schneller als das Umschalten von Dutzenden von Uniformen in einem Programm".

Wenn Sie eine große Anzahl von Lichtern und Parametern haben, können Sie die Daten auch als Float-Puffer senden.

NickLH
quelle
6
Einheitliche Pufferobjekte sind erst seit GL Version 3.1 verfügbar. Die Erweiterung ARB_Uniform_Buffer_Object wird seit Version 2.0 benötigt.
Paul Wendler
94
Wenn Sie "glsl uniform array" googeln, wird diese Seite jetzt als erstes Ergebnis zurückgegeben !! Was tun wir jetzt?
mlvljr
1
Sie können OpenGL zur Laufzeit abfragen, um die maximale Anzahl von Uniformen mitGlint result; glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, 0, &result);
rwols
13
@mlvljr Wir geben eine rekursive Schleife ein, bis der Stapel überläuft. (Erhalten Sie es?)
Micheal Johnson
@ MichaelJohnson Yeah :)
mlvljr