Im trying to create a material struct and a light struct that I will use in GLSL fragment shader. I can render the scene I have correctly when I have only one struct defined (either material or light) but when I define both of them together the glGetUniformLocation(...) calls return -1 for Material structs (order of defnitions does not matter) as if they are not there or not being used. I need to use the structs for the future use please do not ask me to use PODs. I want to learn how to upload multiple structs as uniforms. Thanks.
Here is the vertex shader:
#version 450
layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 norm;
layout (location = 2) out vec3 v_space_norm;
layout (location = 3) out vec3 v_space_pos;
layout(location = 0) uniform mat4 to_screen_space; // mvp
layout(location = 1) uniform mat4 to_view_space; //mv
layout(location = 2) uniform mat3 normals_to_view_space;
//layout(location = 4) float light_intensity;
void main() {
gl_Position = to_screen_space \* vec4(pos, 1.0);
v_space_norm = normals_to_view_space \* norm;
v_space_pos = (to_view_space \* vec4(pos, 1.0)).xyz;
}
and fragment shader:
#version 450
precision mediump float;
//------------ Structs ------------
// struct Light{
// vec3 position;
// float intensity;
// };
//------------ Variying ------------
layout (location = 2) in vec3 v_space_norm;
layout (location = 3) in vec3 v_space_pos;
//------------ Uniforms ------------
layout(location = 1) uniform mat4 to_view_space; //mv
//layout(location = 3) uniform vec3 light_position;
//layout(location = 4) uniform float light_intensity;
layout(location = 3) uniform struct{
vec3 position;
float intensity;
}light;
layout(location = 6) uniform struct{
vec3 ka;
vec3 kd;
vec3 ks;
float shininess;
} material;
out vec4 color;
void main() {
vec3 v_space_norm = normalize(v_space_norm);
vec3 l = normalize( (to_view_space * vec4(light.position, 1)).xyz - v_space_pos);//normalize(l); //light vector
vec3 h = normalize(l + vec3(0,0,1)); //half vector
float cos_theta = dot(l, v_space_norm);
if(cos_theta >= 0)
{
vec3 diffuse = material.kd * max(cos_theta,0);
vec3 ambient = material.ka;
vec3 specular= material.ks * pow(max(dot(h, v_space_norm),0), material.shininess);
color = vec4(light.intensity * (specular + diffuse) + ambient, 1);
}
else
{
color = vec4(material.ka,1);
}
}
And the way I set uniforms:
...
program->SetUniform("light.position", light.position);
program->SetUniform("light.intensity", light.intensity);
program->SetUniform("material.ka", material.ambient);
program->SetUniform("material.kd", material.diffuse);
program->SetUniform("material.ks", material.specular);
program->SetUniform("material.shininess", material.shininess);
...
The definition of SetUniform:
GLint location = glGetUniformLocation(glID, name);
if (location == -1)
{
std::cout << "ERROR::SHADER::UNIFORM::" << name << "::NOT_FOUND"<<std::endl;
return;
}
glUniform1f(location, value);//or what ever the type is there are definitions for all types!!!
I was unable to find anything online about my problem
I was hoping to see the teapot rendered and blinn shaded. And I can get that if I only define one struct and then upload the other properties as PODs.
So using the fragment shader below:
//------------ Uniforms ------------
layout(location = 1) uniform mat4 to_view_space; //mv
layout(location = 3) uniform vec3 light_position;
layout(location = 4) uniform float light_intensity;
// layout(location = 3) uniform struct{
// vec3 position;
// float intensity;
// }light;
...
//using light_position and light_intensity instead of light.position, light.intensity
Of course setUniform calls are also changed accordingly. enter image description here
But if I use both of the structs I get this: enter image description here
Edit: Instead of accessing via glGetUniformLocation(glID, name); I can manually set each variable via layout location number. Now the question becomes "Can I set the structs using the string variable names?"
Using named structs like:
struct Light{
vec3 position;
float intensity;
};
And then using them as uniforms seems to be the correct way to go according to OpenGL wiki (I could have sworn I tried that but oh well...).
layout(location = 3) uniform Light light;
So,
layout(location = 3) uniform struct{
vec3 position;
float intensity;
}light;
this is either not good or undefined behavior which is beyond my knowledge.