创建一个 GLSL 制服数组?

Posted

技术标签:

【中文标题】创建一个 GLSL 制服数组?【英文标题】:Creating a GLSL Arrays of Uniforms? 【发布时间】:2011-11-11 21:06:05 【问题描述】:

我想留下 OpenGL 的灯光并自己制作。 我希望我的着色器允许使用可变数量的灯光。

我们可以在 GLSL 着色器中声明一个制服数组吗? 如果是这样,我们将如何设置这些制服的价值?

【问题讨论】:

任何想要可变数量的灯的人,只需制作具有适当容量的阵列,并计算当前有多少灯处于活动状态。 GLSL 不允许可变大小的数组(所有数组大小必须是常量、硬编码值)。 【参考方案1】:

是的,这是可能的。您声明统一数组的方式类似于您在 C 中的做法,例如

uniform float v[10];

然后你可以使用glUniform1,2,3,4f,iv设置它们的值

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

【讨论】:

1、2、3、4指的是什么?这是否意味着我只能将数组的值设置为最多四个成员? 这是glUniform1fv 的一个非常聪明/扭曲的用法。有人会认为glUniform1fv 的第二个参数只是一种形式,它应该始终用作 1。 @bobobobo: "所以从技术上讲,你可以使用 glUniform1fv(uniformId, 4, v) 设置统一的 vec4;其中 v 是 4 个浮点数的数组。" 不,你不能。规范非常明确:尺寸和类型必须与制服的尺寸和类型相匹配(使用i 的布尔值和使用1i 的不透明对象除外)。如果你说1f,那么制服必须是 1 个浮点数。否则,GL_INVALID_OPERATION 随之而来。 @MilesRufat-Latre 1234 在像glUniform 这样的函数中讲述了统一变量的类型。 1f 表示单个浮点数,2i 表示 ivec2 等等。这不应与函数采用的第二个count 参数相混淆,该参数是数组大小。所以要上传到uniform vec2 vecs[5];,那就是glUniform2fv(loc, 5, data); @Asad-ullahKhan:不,因为 C 数组到指针衰减。【参考方案2】:

是的,可以在 GLSL 着色器中声明一组制服。只需谷歌“glsl uniform array”获取一些示例(编辑:或查看 datenwolf 的示例)。然而,可以将多少制服发送到不同的显卡是有限制的(至少在旧显卡上,我不确定现在的显卡(尽管我想仍然会有)。

如果你决定走制服路线,我建议使用制服缓冲区。根据http://www.opengl.org/wiki/Uniform_Buffer_Object,“在统一缓冲区绑定之间切换通常比在程序中切换数十个统一更快”。

如果您有大量的灯光和参数,您也可以将数据作为浮点缓冲区发送。

【讨论】:

统一缓冲区对象仅从 GL 3.1 版开始可用。从 2.0 版开始需要 ARB_Uniform_Buffer_Object 扩展。 您可以在运行时查询 OpenGL 以获得最大的制服数量 Glint result; glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, 0, &result);

以上是关于创建一个 GLSL 制服数组?的主要内容,如果未能解决你的问题,请参考以下文章

GLSL:无法获取制服位置

c_cpp 设置GLSL制服

c_cpp 设置GLSL制服

如何将mat4数组作为制服传递

您可以将固定大小的数组作为 GLSL 函数参数传递吗?

GLSL 结构数组 - 内存分配/对齐