uniform int size;
uniform SceneLights lights[size];
void main()
{
for(int i = 0; i < size; i++) {
/* Do Some Calculation */
}
}
这将是我的C ++文件:
for (GLuint i = 0; i < pointLights.size(); i++) {
glUniform3f(glGetUniformLocation(shader, ("pointLights[" + std::to_string(i) + "].position").c_str()), lights[i].someValue);
}
我想这样做是因为我有一个文件,其中包含场景中所有光源的位置(每个场景可能有所不同),所以我想有一个动态数组,该数组可以让我将不同数量的灯光发送到我的着色器。
#1 楼
我认为统一数组不能动态调整大小。在您的情况下,应将数组定义为将要处理的最大灯光数量,然后使用统一的控件来控制对该数组进行的迭代次数。在CPU端,您可以根据'size'变量设置lights []数组的子集。例如
#define MAX_LIGHTS 128
uniform int size;
uniform SceneLights lights[MAX_LIGHTS];
void main()
{
for(int i = 0; i < size; i++) {
/* Do Some Calculation */
}
}
I认为(推测)可能的原因是,如果您的制服列表中有可变大小的数组(取决于另一个制服的值),则无法确定制服的位置。.例如
uniform int arraySize; // offset 0
uniform int myArray[arraySize]; // offset 4
uniform int anotherVar; // offset ????
GLSL不知道要放置anotherVar,因为在计算“ anotherVar”的偏移量之前,需要将arraySize设置为一个值。我想编译器可能很聪明,可以重新排列制服的顺序来解决此问题,但是如果您有2个或更多可变大小的数组,这将再次失败。.
#2 楼
您可以在上载着色器代码时将变量添加为代码。char header[64];
sprintf (header, "const int size = %u;\n", pointLights.size());
然后添加标头(假设您的代码在
char code[]
中):GLchar *source[2] = {(GLchar *)header, (GLchar *)code};
glShaderSource(shader, 2, (const GLchar **)source, NULL);
..
这样,您可以改变大小并快速将其添加到着色器。
有点麻烦,但这是我做到的方式。
评论
还有一些着色器存储缓冲区对象,您可以在这里阅读:khronos.org/opengl/wiki/Shader_Storage_Buffer_Object在vulkan中,像这样在GLSL中声明了“无界数组”:layout(binding = 10)Uniform sampler2D TextureUBA [ ];”(sampler2D只是一个示例),我不确定在OpenGL中如何设置。最后一个版本有很大的限制,但两者的性能都会因访问内存的方式而有所不同。 br />