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?
Antworten:
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);
quelle
glUniform1fv
. Man würde denken, dass der 2. Parameter vonglUniform1fv
nur eine Formalität ist und dass er immer als 1.vec4
mitglUniform1fv( uniformId, 4, v ) ;
demv
eine Anordnung von vier Schwimmern ist.i
Bools und der verwendeten Opake1i
). Wenn Sie sagen1f
, dann muss die Uniform 1 Schwimmer sein. AnsonstenGL_INVALID_OPERATION
folgt.{1234}
in Funktionen wieglUniform
erzählt über den Typ der einheitlichen Variablen. 1f bedeutet einen einzelnen Schwimmer, 2i bedeutet ivec2 und so weiter. Dies sollte nicht mit dem zweitencount
Parameter verwechselt werden, den die Funktion annimmt, nämlich der Arraygröße. Zum Hochladenuniform vec2 vecs[5];
wäre es also soglUniform2fv(loc, 5, data);
.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.
quelle
Glint result; glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, 0, &result);