vec3 lightDir = normalize(lightPos - FragPos);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 halfwayDir = normalize(lightDir + viewDir);
Aswell, the shininess part need to be multiplied (2 to 4 times) when using Blinn-Phong to match Phong only visuals results. As a reminder :
void main()
{
[...]
float spec = 0.0;
if(blinn)
{
vec3 halfwayDir = normalize(lightDir + viewDir);
spec = pow(max(dot(normal, halfwayDir), 0.0), 16.0);
}
else
{
vec3 reflectDir = reflect(-lightDir, normal);
spec = pow(max(dot(viewDir, reflectDir), 0.0), 8.0);
}
// As easy as :
glEnable(GL_FRAMEBUFFER_SRGB);
or in each concerned fragment shader, with more control ( Or actually in post-process pass !)
float gamma = 2.2; // or anything user-set, from uniform.
OutputColor.rgb = pow(OutputColor.rgb, vec3(1.0/gamma));
For Textures, they are mostly edited in sRGB space since application and artists are mostly used to this. We can correct it in shader, or using again a neat openGl command. Often, albedo/diffuse maps are in sRGB, while specular and normals maps are in linear space, so…
// sRGB and sRGBA
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
Or correct it manually in shader.
float gamma = 2.2; // or anything user-set, from uniform.
vec3 diffuseColor = pow (texture(diffuse, UV).rgb, vec3(gamma)); // manual correction
Of course, shadows are absence of light, due to occlusion. When a light ray get blocked by an object, all hidden objects are actually in shadows. We’ll start with Shadow Mapping, which is kinda easy, don’t cost that much, and can be extend into Omnidirectionnal Shadow Maps or Cascaded Shadow Maps