Reputation: 131
I'm trying to set the values of the individual fields of structs in an array. The problem is that in the shader, every single field of the struct has the value 0 assigned to it.
Shader:
struct Light
{
vec3 position;
vec3 color;
float ambient;
float diffuse;
float specular;
float exponent;
};
uniform Light lights[8];
C++:
struct Light
{
vec3 position;
vec3 color;
float ambient;
float diffuse;
float specular;
float exponent;
};
...
std::vector<Light> activeLights;
Light l;
l.position = vec3(-50.0f, 50.0f, 50.0f);
l.color = vec3(1.0f, 1.0f, 1.0f);
l.ambient = 0.15f;
l.diffuse = 0.6f;
l.specular = 0.25f;
l.exponent = 8.0f;
activeLights.push_back(l);
...
for (int i = 0; i < activeLights.size(); i++)
{
glUniform3f(glGetUniformLocation(program, "lights[i].position"),
activeLights[i].position.x,
activeLights[i].position.y,
activeLights[i].position.z
);
glUniform3f(glGetUniformLocation(program, "lights[i].color"),
activeLights[i].color.r,
activeLights[i].color.g,
activeLights[i].color.b
);
glUniform1f(glGetUniformLocation(program, "lights[i].ambient"), activeLights[i].ambient);
glUniform1f(glGetUniformLocation(program, "lights[i].diffuse"), activeLights[i].diffuse);
glUniform1f(glGetUniformLocation(program, "lights[i].specular"), activeLights[i].specular);
glUniform1f(glGetUniformLocation(program, "lights[i].exponent"), activeLights[i].exponent);
}
I checked the values on the c++ side multiple times in the debugger, everything's ok there.
Any ideas?
Upvotes: 4
Views: 643
Reputation: 474376
"lights[i].position"
Unlike some scripting languages, C++ has no mechanism to apply code to a string literal. As such, "lights[i].position"
is always exactly that string. 'i' is not recognized as being anything special; it is the character 'i'.
What you really want to do is generate a string based on the variable i
. Which can be done easily enough:
std::ostringstream strm;
strm << "lights[" << i << "]";
std::string light = strm.str();
There are more efficient ways to do this, but this is the easiest way in C++. In any case, if performance really mattered, you wouldn't be querying uniform locations at runtime.
Now, you have to generate a string for every single uniform member access, then use that string to access that uniform member. So, for each access, you have to do this:
std::string str = light + ".position";
glUniform3f(glGetUniformLocation(program, str.c_str()),
activeLights[i].position.x,
activeLights[i].position.y,
activeLights[i].position.z
);
You can reuse str
, rather than defining new strings.
Upvotes: 6