Custom light and rotation issue

Hi!
After a very long pause from OF, in the last months I finally come back to write some code.
I’m trying to understand the basic of light and shadow following this tutorial:

https://learnopengl.com/Lighting/Lighting-maps

The first result seems fine, but I think actually it isn’t.
I have two issue here:

video

When I rotate the camera, I always see some specular light also in the side of the cube that are not “face to face” with the light. It seems strange to me. What do you think?

The other issue is that when I rotate the cube, the light doesn’t on the cube doesn’t change in the right way. I tried some other way but at the end no one worked. Any idea?

Here my code:

ofApp.cppp

void ofApp::draw(){
  cam.begin();
  ofEnableDepthTest();
  
  shader.begin();
  shader.setUniform1i("useTextureMaterial", useTextureMaterial);
  shader.setUniformTexture("diffuseText", textureImage.getTexture() , 1);
  shader.setUniform3f("viewPos", cam.getGlobalPosition());
  
  // Light
  shader.setUniform3f("light.position", lightPos);
  shader.setUniform3f("light.ambient", lightAmbientColor.r/255.0, lightAmbientColor.g/255.0, lightAmbientColor.b/255.0);
  shader.setUniform3f("light.diffuse", lightDiffuseColor.r/255.0, lightDiffuseColor.g/255.0, lightDiffuseColor.b/255.0);
  shader.setUniform3f("light.specular", lightSpecular, lightSpecular, lightSpecular);
  // Material
  shader.setUniform3f("material.ambient", materialAmbientColor.r/255.0, materialAmbientColor.g/255.0, materialAmbientColor.b/255.0);
  shader.setUniform3f("material.diffuse", materialDiffuseColor.r/255.0, materialDiffuseColor.g/255.0, materialDiffuseColor.b/255.0);
  shader.setUniform3f("material.specular", materialSpecular, materialSpecular, materialSpecular);
  shader.setUniform1f("material.shininess",  pow(2, (int)materialShininess));
  // Texture material
  shader.setUniform1f("textMaterial.shininess",  pow(2, (int)materialShininess));
  shader.setUniformTexture("textMaterial.diffuse", textureImage.getTexture() , 0);
  shader.setUniformTexture("textMaterial.specular", textureSpecularImage.getTexture() , 1);
  
  drawScene();
  shader.end();
  drawLights();
  ofDisableDepthTest();
  cam.end();
}

void ofApp::drawLights(){
  ofPushMatrix();
  ofTranslate(lightPos);
  ofSetColor(255);
  light.getMesh().draw();
  ofPopMatrix();
}

void ofApp::drawScene(){
  ofPushMatrix();
  ofTranslate(cubePos);
  ofRotateXDeg(cubeRotation);
  //  cube.setPosition(cubePos);
  shader.setUniformMatrix4f("model", cube.getGlobalTransformMatrix());
  cube.getMesh().draw();
  ofPopMatrix();
}

Vertex

#version 330
//Default from OF::programmableRenderer
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 cubeModelMatrix;

//Default from OF::shader
in vec4  position;
in vec3 normal;
in vec2  texcoord;
out vec3 FragPos;
out vec3 Normal;
//Out for frag
out vec4 colorVarying;
out vec2 TexCoords;

//Uniform setup in ofApp
uniform mat4 modView;
uniform mat4 model;

void main() {
//  mat3 normalMatrix = transpose(inverse(mat3(model)));
//  Normal = normalMatrix * vec3(normal).xyz;
  gl_Position = projectionMatrix * viewMatrix * modelMatrix * position;
  FragPos = vec3(modelMatrix * vec4(position.xyz, 1.0));
  Normal = normal;
  TexCoords = texcoord;
}

Fragment:

#version 330

struct Material {
  vec3 ambient;
  vec3 diffuse;
  vec3 specular;
  float shininess;
};

struct Light {
  vec3 position;
  
  vec3 ambient;
  vec3 diffuse;
  vec3 specular;
};

struct TextureMaterial {
  sampler2D diffuse;
  sampler2D specular;
  float     shininess;
};

uniform Light light;
uniform Material material;
uniform TextureMaterial textMaterial;

uniform mat4 modelViewMatrix;
uniform mat4 modelMatrix;
uniform vec3 lightColor;
uniform vec3 cubeColor;
uniform vec3 viewPos;
uniform bool useTextureMaterial;

in vec2 TexCoords;
in vec3 Normal;
in vec3 FragPos;
out vec4 fragColor;


void main (void) {
  vec3 norm = normalize(Normal.xyz);
  vec3 lightDir = normalize(light.position - FragPos);
  float diff = max(dot(norm, lightDir), 0.0);
  vec3 viewDir = normalize(viewPos - FragPos);
  vec3 reflectDir = reflect(-lightDir, norm);
  vec3 result;
  vec3 ambient;
  vec3 diffuse;
  vec3 specular;
  float shininess = (useTextureMaterial) ? textMaterial.shininess : material.shininess;
  float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
  if(!useTextureMaterial){
    ambient = light.ambient * material.ambient;
    diffuse = light.diffuse * (diff * material.diffuse);
    specular = light.specular * (material.specular * spec);
  }
  else{
    ambient = light.ambient * vec3(texture(textMaterial.diffuse, TexCoords));
    diffuse = light.diffuse * diff * vec3(texture(textMaterial.diffuse, TexCoords));
    specular = light.specular * spec * vec3(texture(textMaterial.specular, TexCoords));
  }
  result = ambient + diffuse + specular;
  fragColor = vec4(result, 1.0);
}

Thanks!

Looking around on the web I solved my second issue. I need to multiply my normal with the inverse traspose of the model matrix. I’m not 100% sure, but I understood that I need to do this multiplication if I know that I need to scale or rotate my mesh.
Unfortunately I don’t understand the math reason of this multiplication… for now it’s just faith.

So, my new fragment is that:

void main() {
  gl_Position = projectionMatrix * viewMatrix * modelMatrix * position;
  FragPos = vec3(modelMatrix * vec4(position.xyz, 1.0));
  Normal = ( inverse(transpose(modelMatrix)) * vec4(normal, 0.0)).xyz;
  TexCoords = texcoord;
}