I have a shader written in GLSL with an array of structs for holding light data. I use a constant to declare the array size, as is good practice. Let's say this variable is declared as
const int NUM_POINT_LIGHTS = 100;
How can I use C++ to pull this data out of the shader, so that my C++ program knows exactly how many lights it has available to it? I've tried declaring it as
const uniform int NUM_POINT_LIGHTS = 100;
As expected, this didn't work (though oddly enough, it appears as though the uniform specification simply overrode the const specification, as the OpenGL complained that I was initializing an array with a non-const value). I also tried
const int NUM_POINT_LIGHTS = 100;
uniform numPointLights = NUM_POINT_LIGHTS;
This would work, except for the fact that GLSL optimizes away unused uniforms so I have to track glsl into thinking the uniform is used somehow in order to be able to get a hold of the data. I've not been able to find any other method to query a program to get a constant value. Does anybody have any ideas how I might be able to pull a constant out of a shader so my program to get information that is functionally encoded in the shader for it's use?
I don't think you can directly get the value of the constant. However, I figure you must use the value of the constant, most likely as the size of a uniform array. If that's the case, you can get the size of the uniform array, which indirectly gets you the value of the constant.
Say your shader contains something like this:
const int NUM_POINT_LIGHTS = 100;
uniform vec3 LightPositions[NUM_POINT_LIGHTS];
Then you can first get the index of this uniform:
const GLchar* uniformName = "LightPositions";
GLuint uniformIdx = 0;
glGetUniformIndices(program, 1, &uniformName, &uniformIdx);
Using this index, you can then retrieve attributes of this uniform:
const int nameLen = strlen("LightPositions") + 1;
const GLchar name[nameLen];
GLint uniformSize = 0;
GLenum uniformType = GL_NONE;
glGetActiveUniform(program, uniformIdx, nameLen, NULL,
&uniformSize, &uniformType, name);
uniformSize
should then be the value of the NUM_POINT_LIGHTS
constant. Note that I haven't tried this, but I hope I got the arguments right based on the documentation.
A somewhat ugly but possibly very practical solution is of course to parse the value out of the shader source code. Since you need to read it in anyway before passing it to glShaderSource()
, picking out the constant value should be easy enough.
Yet another option, if your main goal is to avoid having the constant in multiple places, is to define it in your C++ code, and add the constant definition to the shader code dynamically after reading in the shader code, and before passing it go glShaderSource()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With