1
$\begingroup$

Consider the following code in an OpenGL shader:

struct PointLight {
    vec3 position;

    float constant;
    float linear;
    float quadratic;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};
uniform PointLight pointLights[4];

How can I query the size of pointLights using interface query? I tried this:

auto idx = glGetProgramResourceIndex(prog, GL_UNIFORM, "pointLights");
auto blockProperty = (GLenum)GL_ARRAY_SIZE;
auto arraySize = GLint{};
glGetProgramResourceiv(prog, GL_UNIFORM, idx, 1, &blockProperty, 1, nullptr, &arraySize);

It returns 0, which corresponds to the documentation of glGetProgramResourceiv:

For active variables not corresponding to an array of basic types, the value zero is written to params.

Well, what should I do for non-basic types?

$\endgroup$
6
  • $\begingroup$ Generally speaking, you shouldn't allow shaders to dictate information like how many lights it allows. This is something the shader and the code using it need to agree on, not something that should be deduced from how the shader is written. $\endgroup$ Feb 26 at 2:10
  • $\begingroup$ And what is the proper way to agree on it? The array size in the shader is a GLSL compile time constant, I cannot set it from my C++ code. $\endgroup$
    – facetus
    Feb 26 at 3:19
  • $\begingroup$ A person wrote the shader. A person wrote the code that consumes the shader. If these aren't the same people, then they need to talk to each other and get on the same page about what's going on in the shader. This could be an actual meeting or documentation on how to use the engine or whatever. Alternatively, you could use UBOs. $\endgroup$ Feb 26 at 3:46
  • $\begingroup$ It's not how usually modules of software agree on things, if they want to avoid a disaster. There is a constant set somewhere in one module, then it gets advertised to other modules. Otherwise, one day Vasya Pupkin decides to change a constant, and everything explodes. See the maiden flight of Ariane 5 on June 4, 1996. $\endgroup$
    – facetus
    Feb 26 at 4:01
  • $\begingroup$ "There is a constant set somewhere in one module, then it gets advertised to other modules." That's great... when you're working in a single language. If you're working across non-interoperable languages, you can't do that easily. Eventually, it has to come down to some sort of convention. After all, you both had to agree that pointLights is an array of PointLight structures which contain certain fields with certain names, right? Adding one number to this list is hardly out of left field. $\endgroup$ Feb 26 at 6:02

1 Answer 1

1
$\begingroup$

To the uniform query API, there is no such thing as an "array of non-basic types". There are just a bunch of uniforms that just so happen to have names that include array notation like "pointLights[1].constant".

Put another way, pointLights is not a uniform. Nor is pointLights[1]. Only the elements the aggregate are themselves uniforms. And as far as the API is concerned, "pointLights[1].constant" is a completely separate uniform from the one named "pointLights[3].constant" with no relationship between them.

This is in part because you cannot set arrays of non-basic types with a single call. That is, there's no equivalent to glProgramUniform4fv, which has the ability to set a vec4[N] array uniform in a single function call.

So if you want to know how big some array of aggregates is, you're going to have to deduce it by iterating through all of the uniform names and comparing them to see which has the largest index.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.