创建GLSL统一数组?

84

我希望自己制作着色器中的灯光,不使用OpenGL的灯光。 我想让我的着色器能够容纳可变数量的灯光。

我们能否在GLSL着色器中声明一个uniform数组? 如果可以,我们该如何设置这些uniform的值?


5
想要可变数量的灯光,只需使用具有良好容量的数组,并记录当前激活的灯光数量。GLSL不允许变量大小的数组(所有数组大小必须是常数硬编码值)。 - Miles
2个回答

116
是的,这是可能的。你可以声明统一的数组,就像在 C 语言中那样,例如:
uniform float v[10];

然后,您可以使用glUniform{1,2,3,4}{f,i}v设置它们的值。

GLfloat v[10] = {...};
glUniform1fv(glGetUniformLocation(program, "v"), 10, v);

2
1、2、3、4指的是什么?这是否意味着我只能将数组的值设置为最多四个成员? - Miles
@bobobobo:好问题。老实说我还不知道,但我不建议这样做。GLSL数据类型有点反映了glUniform<n>的n。 - datenwolf
21
“@bobobobo:“所以在使用glUniform1fv(uniformId,4,v);时,你可以使用一个由4个浮点数组成的数组v来设置一个统一的vec4。”不,你不能这样做。规范非常清楚:大小和类型必须*与统一变量的大小和类型匹配(除了使用i的布尔值和使用1i的不透明度)。如果你说1f,那么统一变量必须是1个浮点数。否则,将导致“GL_INVALID_OPERATION”。” - Nicol Bolas
10
在像glUniform这样的函数中,{1234}表示uniform变量的类型。例如,1f代表单个浮点数,2i代表ivec2等等。这不应与函数使用的第二个参数count混淆,该参数表示数组大小。因此,要上传到uniform vec2 vecs [5];,应使用glUniform2fv(loc,5,data); - legends2k
2
@Asad-ullahKhan:不行,因为C数组会衰减成指针。 - datenwolf
显示剩余3条评论

5
可以在GLSL着色器中声明一个uniform数组。只需搜索“glsl uniform array”以获取一些示例(编辑:或查看datenwolf的示例)。但是,对于不同的显卡,有多少uniform可以发送存在限制(至少对于旧显卡,我不确定当前的显卡情况(尽管我认为仍然会有限制))。
如果您决定使用uniform,建议使用统一缓冲区对象。根据http://www.opengl.org/wiki/Uniform_Buffer_Object,“在程序中切换uniform缓冲区绑定通常比切换几十个uniform更快”。
如果您有大量灯光和参数,还可以将数据作为浮动缓冲区发送。

7
自GL(OpenGL)版本3.1起,Uniform buffer objects(统一缓冲对象)才被引入。需要使用ARB_Uniform_Buffer_Object扩展,该扩展自OpenGL版本2.0起可用。 - Paul Wendler
1
您可以在运行时查询OpenGL以获取最大统一变量数,使用Glint result; glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, 0, &result)即可。 - rwols
3
我在谷歌上搜索了一下并找到了这个页面。以后回答问题时最好提前做好应对这种情况的计划 :) - EugZol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接