简体   繁体   English

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

[英]Get the size of compiled glsl shader uniform parameter from C++ code

I am trying to get the size of uniform parameter in already compiled glsl shader program. 我试图在已经编译的glsl shader程序中获得统一参数的大小。 I have found some functions to do it for default-typed uniforms only. 我发现一些功能仅适用于默认类型的制服。 But is there a way to do it for uniform parameters with custom type? 但是,有没有一种方法可以对具有自定义类型的统一参数进行处理呢?

For example: 例如:

struct Sphere
{
    vec3 position;
    float raduis;
};

#define SPHERES 10
uniform Sphere spheres[SPHERES];

I'm assuming that your end goal basically is spheres.length and the result being 10 . 我假设您的最终目标基本上是spheres.length ,结果是10

The most optimal way would be to have that length stored elsewhere, as it isn't possible to change the size after the shader has been compiled anyways. 最佳的方法是将该长度存储在其他位置,因为无论如何在着色器编译后就无法更改大小。


There's no simple way to get the length of the array. 没有简单的方法来获取数组的长度。 Because there isn't any array per se. 因为本身没有任何数组。 When compiled each element of the array (as well as each element of the struct) ends up becoming their own individual uniform. 编译时,数组的每个元素(以及结构的每个元素)最终成为它们自己的统一体。 Which is evident by the need of doing: 通过执行以下操作可以明显看出这一点:

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

The thing is that if your shader only uses spheres[4].position and spheres[8].position then all the other spheres[x].position are likely to be optimized away and thus won't exist. 问题是,如果您的着色器仅使用spheres[4].positionspheres[8].position则所有其他spheres[x].position可能会被优化掉,因此将不存在。


So how do you get the uniform array length? 那么如何获得统一的数组长度?

You could accomplish this by utilizing glGetActiveUniform() and regex or sscanf() . 您可以通过使用glGetActiveUniform()和regex或sscanf()来完成此操作。 Say you want to check how many spheres[x].position is available, then you could do: 假设您要检查有多少个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
    }
}

You can additionally compare type to GL_FLOAT or GL_FLOAT_VEC3 to figure out which data type it is. 您还可以将typeGL_FLOATGL_FLOAT_VEC3进行比较,以确定它是哪种数据类型。

Remember that if you add an int count and increment it for each match. 请记住,如果您添加一个int count并为每个匹配项增加它。 Then even if count is 3 at the end. 然后,即使最后count3 That doesn't mean it's element 0, 1, 2 that's available. 这并不意味着可用元素0, 1, 2 It could easily be element 0, 5, 8 . 它很容易是元素0, 5, 8

Additional notes: 补充笔记:

  • name is a null terminated string name是一个以空值终止的字符串
  • %n is the number of characters read so far %n是到目前为止已读取的字符数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM