简体   繁体   中英

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. 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 .

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.


So how do you get the uniform array length?

You could accomplish this by utilizing glGetActiveUniform() and regex or sscanf() . Say you want to check how many spheres[x].position is available, then you could do:

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.

Remember that if you add an int count and increment it for each match. Then even if count is 3 at the end. That doesn't mean it's element 0, 1, 2 that's available. It could easily be element 0, 5, 8 .

Additional notes:

  • name is a null terminated string
  • %n is the number of characters read so far

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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