从C++代码中获取编译后的GLSL着色器统一参数的大小

从C++代码中获取编译后的GLSL着色器统一参数的大小,c++,opengl,glsl,C++,Opengl,Glsl,我试图在已经编译的glsl着色器程序中获得统一参数的大小。我已经找到了一些函数,只用于默认类型的制服。但是,有没有一种方法可以对具有自定义类型的统一参数执行此操作 例如: struct Sphere { vec3 position; float raduis; }; #define SPHERES 10 uniform Sphere spheres[SPHERES]; 我假设你的最终目标基本上是spheres.length,结果是10 最理想的方法是将该长度存储在其他位置,因

我试图在已经编译的glsl着色器程序中获得统一参数的大小。我已经找到了一些函数,只用于默认类型的制服。但是,有没有一种方法可以对具有自定义类型的统一参数执行此操作

例如:

struct Sphere
{
    vec3 position;
    float raduis;
};

#define SPHERES 10
uniform Sphere spheres[SPHERES];

我假设你的最终目标基本上是spheres.length,结果是10

最理想的方法是将该长度存储在其他位置,因为无论如何在编译着色器后都不可能更改大小

没有简单的方法可以获得数组的长度。因为本身没有任何数组。在编译时,数组的每个元素以及结构的每个元素最终都成为各自的统一元素。这一点很明显,需要做:

glGetUniformLocation(program, "spheres[4].position")
问题是,如果着色器仅使用球体[4]。位置和球体[8]。位置,则所有其他球体[x]。位置都可能被优化掉,因此不存在

那么,如何获得统一的数组长度呢

您可以通过使用glGetActiveUniform和regex或sscanf来实现这一点。假设要检查有多少个球体[x]。位置可用,则可以执行以下操作:

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
    }
}
您还可以将类型与GL_FLOAT或GL_FLOAT_VEC3进行比较,以确定它是哪种数据类型

请记住,如果您添加一个int计数并为每个匹配递增它。即使最后的计数是3。这并不意味着元素0、1、2可用。它很可能是元素0、5、8

补充说明:

名称是以null结尾的字符串 %n是到目前为止读取的字符数
感谢您的解释,但我的问题是,如果统一变量具有用户定义的类型,如何通过其名称获取其大小。对不起,我在这里添加了数组来显示最难的情况,但我想这会让我的问题变得不清楚。所以,这里有一个更简单的统一声明:统一球体;我想从我的C++代码中得到球的大小,我的答案已经涵盖了这个问题。使用类型。问题是没有sizeofsphere[i],因为没有sphere[i]本身。只有每个元素都映射到一个统一的元素。因此,您必须检查每个球体[i].*。然后检查它们的类型,然后得出最终尺寸。因此,如果要检查数组的最终大小,必须检查每个球体。*。