我试图在已经编译的glsl shader程序中获得统一参数的大小。我发现一些功能仅适用于默认类型的制服。但是,有没有一种方法可以对具有自定义类型的统一参数进行处理呢?
例如:
struct Sphere
{
vec3 position;
float raduis;
};
#define SPHERES 10
uniform Sphere spheres[SPHERES];
最佳答案
我假设您的最终目标基本上是spheres.length
,结果是10
。
最佳的方法是将该长度存储在其他位置,因为无论如何在着色器编译后就无法更改大小。
没有简单的方法来获取数组的长度。因为本身没有任何数组。编译时,数组的每个元素(以及结构的每个元素)最终成为它们自己的统一体。通过执行以下操作可以明显看出这一点:
glGetUniformLocation(program, "spheres[4].position")
问题是,如果您的着色器仅使用
spheres[4].position
和spheres[8].position
,则所有其他spheres[x].position
可能都已被优化掉,因此将不存在。那么如何获得统一的数组长度?
您可以通过使用
glGetActiveUniform()
和正则表达式或sscanf()
来完成此操作。假设您要检查多少spheres[x].position
可用,则可以执行以下操作:GLint count;
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count);
const GLsizei NAME_MAX_LENGTH = 64
GLint location, size;
GLenum type;
GLchar name[NAME_MAX_LENGTH];
GLsizei nameLength;
int index, charsRead;
for (GLint i = 0; i < count; ++i)
{
glGetActiveUniform(program, (GLuint)i, NAME_MAX_LENGTH, &nameLength, &size, &type, name);
if (sscanf(name, "spheres[%d].position%n", &index, &charsRead) && (charsRead == nameLength))
{
// Now we know spheres[index].position is available
}
}
您还可以将
type
与GL_FLOAT
或GL_FLOAT_VEC3
进行比较,以确定它是哪种数据类型。请记住,如果添加
int count
并为每个匹配项增加它。然后即使count
最后是3
。这并不意味着它是元素0, 1, 2
可用。它很容易是元素0, 5, 8
。补充说明:
name
是空终止的字符串%n
是到目前为止已读取的字符数