I have a strange problem I can’t figure out. On the CPU I have a class that handles the material properties for a model.
material = new Material();
material->Emissive = vec3(0.1, 0.0, 0.0);
material->Ambient = vec3(0.1, 0.0, 0.0);
material->Diffuse = vec3(1.0, 0.0, 0.0);
material->Specular = vec3(1.0, 1.0, 1.0);
material->Shininess = 10.0f;
material->Alpha = 1.0f;
To send them to the GPU, I have some methods in my Program class (a class for adding shaders, vertex attributes, uniforms etc):
program->Uniform3fv("uniEmissive", material->Emissive);
program->Uniform3fv("uniAmbient", material->Ambient);
program->Uniform3fv("uniDiffuse", material->Diffuse);
program->Uniform3fv("uniSpecular", material->Specular);
program->Uniform1f("uniShininess", material->Shininess);
program->Uniform1f("uniAlpha", material->Alpha);
Which internally looks like this
// This map stores names and locations for a uniform
map<GLchar*, GLint> uniformList;
void Program::Uniform3fv(GLchar *name, glm::vec3 value)
{
if (!UniformListContains(name))
{
AddUniformLocation(name);
}
if (UniformListContains(name))
{
glUniform3fv(uniformList[name], 1, glm::value_ptr(value));
}
}
void Program::AddUniformLocation(GLchar *name)
{
GLint location = glGetUniformLocation(program, name);
if (location != -1)
{
uniformList.insert(pair<GLchar*, GLint>(name, location));
}
else
{
printf("Error: the uniform \"%s\" doesn't exist, or isn't used, in program
", name);
}
}
The
uniformList
is a map with name of the uniform in the shader and the location of the uniform. So first in this function it looks if it is in the list, if not it adds it. Then it uploads the value to the GPU, by looking in the
uniformList
for this name, and if found it retuns the location for the uniform. This is how the
uniformList
looks when everything for this program has been uploaded. Which seems correct to me, because none of the indices are -1.
[ATTACH=CONFIG]780[/ATTACH]
So, now to the problem. In my fragment shader I have this code
vec3 N = normalize(normal);
vec3 L = normalize(lightDir);
vec3 R = reflect(-L, N);
vec3 V = normalize(-position);
vec3 emissive = uniEmissive;
vec3 ambient = uniAmbient;
vec3 diffuse = uniDiffuse * max(dot(N, L), 0.0);
vec3 specular = uniSpecular * pow(max(dot(R, V), 0.0), uniShininess);
fragColor = vec4(emissive + ambient + diffuse + specular, uniAlpha);
This, doesn’t work! But if I remove “emissive” it renders the model properly. Also, if I just use
vec4(emissive, uniAlpha)
it also renders the model, and with a very dark red color, which is correct.
Another way it is working is by “hard coding” the material properties in the shader, note: emissive is used here also.
vec3 Emissive = vec3(0.1, 0.0, 0.0);
vec3 Ambient = vec3(0.1, 0.0, 0.0);
vec3 Diffuse = vec3(1.0, 0.0, 0.0);
vec3 Specular = vec3(1.0, 1.0, 1.0);
float Shininess = 10.0;
float Alpha = 1.0;
vec3 emissive = Emissive;
vec3 ambient = Ambient;
vec3 diffuse = Diffuse * max(dot(N, L), 0.0);
vec3 specular = Specular * pow(max(dot(R, V), 0.0), Shininess);
fragColor = vec4(emissive + ambient + diffuse + specular, Alpha);
Also, I tried some other combinations with the uniforms, some of them works. Look at the comments in the code block below.
vec3 diffuse = uniDiffuse * max(dot(N, L), 0.0);
vec3 specular = uniSpecular * pow(max(dot(R, V), 0.0), uniShininess);
// This works, 1.0 instead of uniAlpha.
fragColor = vec4(uniEmissive + uniAmbient + diffuse + specular, 1.0);
// Doesn't work, added uniAlpha
fragColor = vec4(uniEmissive + uniAmbient + diffuse + specular, uniAlpha);
// These are working
fragColor = vec4(uniEmissive, uniAlpha);
fragColor = vec4(uniEmissive + uniAmbient, uniAlpha);
// Adding diffuse doesn't work.
fragColor = vec4(uniEmissive + uniAmbient + diffuse, uniAlpha);
// Just diffuse, works!
fragColor = vec4(diffuse, uniAlpha);
Also running
glGetShaderInfoLog
gives no errors. When I say not working I mean that the model isn’t rendered at all. I hope someone has time to look through this, thanks in advance!