title: Normal Mapping, Specular Mapping and Ambient Mapping
body: <p>I have been using <a href="http://www.opengl-tutorial.org/" rel="nofollow">http://www.opengl-tutorial.org/</a> and my shaders below are derived from his tutorials, mainly I have changed variable names and I removed the tag v coord inversion because I am using a dds image. I did replace a vec3 with a value from an ambient texture as well.</p>
  
  <p>Vertex Shader</p>
  
  <pre><code>#version 330 core
  
  // Input vertex data, different for all executions of this shader.
  layout(location = 0) in vec3 modelVertex;
  layout(location = 1) in vec2 uv;
  layout(location = 2) in vec3 modelNormal;
  layout(location = 3) in vec3 modelVertexTangent;
  layout(location = 4) in vec3 modelVertexBitangent;
  
  // Output data will be interpolated for each fragment.
  out vec2 texcoord;
  out vec3 worldPosition;
  out vec3 cameraEyeDirection;
  out vec3 cameraLightDirection;
  out vec3 lightDirectionTangent;
  out vec3 eyeDirectionTangent;
  
  // Values that stay constant for the whole mesh.
  uniform mat4 MVP;
  uniform mat4 V;
  uniform mat4 M;
  uniform mat3 MVR;
  uniform vec3 worldLightPosition;
  
  void main()
  {
      // Output position of the vertex, in clip space : MVP * position
      gl_Position =  MVP * vec4(modelVertex,1);
  
      // Position of the vertex, in worldspace : M * position
      worldPosition = (M * vec4(modelVertex,1)).xyz;
  
      // Vector that goes from the vertex to the camera, in camera space.
      // In camera space, the camera is at the origin (0,0,0).
      vec3 cameraVertexPosition = (V * M * vec4(modelVertex,1)).xyz;
      cameraEyeDirection = vec3(0,0,0) - cameraVertexPosition;
  
      // Vector that goes from the vertex to the light, in camera space. M is ommited because it's identity.
      vec3 cameraLightPosition = ( V * vec4(worldLightPosition,1)).xyz;
      cameraLightDirection = worldLightPosition + cameraEyeDirection;
  
      // UV of the vertex. No special space for this one.
      texcoord = uv;
  
      // model to camera = ModelView
      vec3 cameraVertexTangent = MVR * normalize(modelVertexTangent);
      vec3 cameraVertexBitangent = MVR * normalize(modelVertexBitangent);
      vec3 cameraVertexNormal = MVR * normalize(modelNormal);
  
      // You can use dot products instead of building this matrix and transposing it. See References for details.
      mat3 tbn = transpose(mat3(cameraVertexTangent,cameraVertexBitangent,cameraVertexNormal)); 
  
      lightDirectionTangent = tbn * cameraLightDirection;
      eyeDirectionTangent =  tbn * cameraEyeDirection;
  }
  </code></pre>
  
  <p>Fragment Shader</p>
  
  <pre><code>#version 330 core
  
  // Interpolated values from the vertex shaders
  in vec2 texcoord;
  in vec3 worldPosition;
  in vec3 cameraEyeDirection;
  in vec3 cameraLightDirection;
  
  in vec3 lightDirectionTangent;
  in vec3 eyeDirectionTangent;
  
  // Ouput data
  out vec3 color;
  
  // Values that stay constant for the whole mesh.
  uniform sampler2D diffuseTextureSampler;
  uniform sampler2D normalTextureSampler;
  uniform sampler2D specularTextureSampler;
  uniform sampler2D ambientTextureSampler;
  uniform mat4 V;
  uniform mat4 M;
  uniform mat3 MVR;
  uniform vec3 worldLightPosition;
  
  uniform float LightPower;
  uniform vec3 LightColor;
  
  void main()
  {
      // Light emission properties
      // You probably want to put them as uniforms
  
      // Material properties 
      vec3 MaterialDiffuseColor = texture2D(diffuseTextureSampler, texcoord).rgb;
      vec3 MaterialAmbientColor = texture2D(ambientTextureSampler, texcoord).rgb * MaterialDiffuseColor;
      vec3 MaterialSpecularColor = texture2D(specularTextureSampler, texcoord).rgb * 0.3;
  
      // Local normal, in tangent space.
      vec3 tangentTextureNormal = normalize(texture2D(normalTextureSampler, texcoord).rgb*2.0 - 1.0);
  
      // Distance to the light
      float distanceBetween = length(worldLightPosition - worldPosition);
  
      // Normal of the computed fragment, in camera space
      vec3 n = tangentTextureNormal;
  
      // Direction of the light (from the fragment to the light)
      vec3 l = normalize(lightDirectionTangent);
  
      // Cosine of the angle between the normal and the light direction, 
      // clamped above 0
      //  - light is at the vertical of the triangle -&gt; 1
      //  - light is perpendicular to the triangle -&gt; 0
      //  - light is behind the triangle -&gt; 0
      float cosTheta = clamp(dot(n,l),0,1);
  
      // Eye vector (towards the camera)
      vec3 E = normalize(eyeDirectionTangent);
  
      // Direction in which the triangle reflects the light
      vec3 R = reflect(-l,n);
  
      // Cosine of the angle between the Eye vector and the Reflect vector,
      // clamped to 0
      //  - Looking into the reflection -&gt; 1
      //  - Looking elsewhere -&gt; &lt; 1
      float cosAlpha = clamp(dot(E,R),0,1);
  
      color = MaterialAmbientColor +  // Ambient : simulates indirect lighting
          MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distanceBetween*distanceBetween) + // Diffuse : "color" of the object      
          MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distanceBetween*distanceBetween);  //Specular
  
  }
  </code></pre>
  
  <p>So what I have already tested for, this is not a issue with loading the shader or generating the values that my model has, I am following is tutorial to a 'T' for those parts.</p>
  
  <p>The model appears textured with the diffuse, and darker across the whole model rather than per vertex as would be expected, I cannot see the normal or specular mapping at all. I have added a light position as a shader parameter, I picked coords by loading my model in maya and picking a spot for my light.</p>
  
  <p>All the textures are stock textures generated from maya/mudbox, the only thing I did was convert to dds DXT3 and flip the textures.</p>
  
  <p>I am guessing I am missing something in my shader.</p>