从C ++代码获取已编译的glsl着色器统一参数的大小

时间:2017-04-11 22:20:23

标签: c++ opengl glsl

我正在尝试在已编译的glsl着色器程序中获取uniform参数的大小。我发现一些函数只能用于默认类型的制服。但有没有办法为自定义类型的统一参数做到这一点?

例如:

struct Sphere
{
    vec3 position;
    float raduis;
};

#define SPHERES 10
uniform Sphere spheres[SPHERES];

1 个答案:

答案 0 :(得分:1)

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

最佳方式是将长度存储在其他位置,因为在编译着色器之后无法更改大小。

没有简单的方法来获得数组的长度。因为本身没有任何数组。编译时,数组的每个元素(以及结构的每个元素)最终成为他们自己的个体制服。这需要做的很明显:

glGetUniformLocation(program, "spheres[4].position")

问题在于,如果您的着色器仅使用spheres[4].positionspheres[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
    }
}

您还可以将typeGL_FLOATGL_FLOAT_VEC3进行比较,以确定它是哪种数据类型。

请记住,如果您添加int count并为每次匹配增加它。然后,即使最后count3。这并不意味着它的元素0, 1, 2可用。它可以很容易地是元素0, 5, 8

附加说明:

  • name是一个以空字符结尾的字符串
  • %n是到目前为止读取的字符数