title: OpenGL - Making a point light that follows the camera
body: <p>I'm currently creating a 3D scene, and I was wondering what would be the best way to go about creating a point light that follows the camera. So far my code is as follows:</p>
  
  <p>Vertex shader:</p>
  
  <pre><code>// Materials
  uniform vec3 materialAmbient;
  uniform vec3 materialDiffuse;
  uniform vec3 materialSpecular;
  uniform float materialShininess;
  
  uniform float att_quadratic = 0.1;
  
  // Lights
  struct AMBIENT
  {   
      vec3 color;
  };
  struct DIRECTIONAL
  {   
      vec3 direction;
      vec3 diffuse;
  };
  struct POINT
  {   int on;
      int frag;
      vec3 position;
      vec3 diffuse;
      vec3 specular;
  };
  
  uniform AMBIENT lightAmbient;
  uniform DIRECTIONAL lightDir;
  uniform POINT lightPoint1, lightPoint2, lightPoint3;
  
  layout (location = 0) in vec3 aVertex;
  layout (location = 2) in vec3 aNormal;
  layout (location = 3) in vec2 aTexCoord;
  
  // Output (sent to Fragment Shader)
  out vec4 color;
  out vec4 position;
  out vec4 normal;
  out vec2 texCoord;
  out float gravelFactor;     // gravelFactor is 1 within the gravel circle and 0 outside the circle
  
  vec4 compAmbient(vec3 material, AMBIENT light)
  {
      return vec4(material * light.color, 1);
  }
  
  vec4 compDirectional(vec3 material, DIRECTIONAL light)
  {
      vec3 L = normalize(mat3(matrixView) * light.direction).xyz;
      float NdotL = dot(normal.xyz, L);
      if (NdotL &gt; 0)
          return vec4(light.diffuse * material * NdotL, 1);
      else
          return vec4(0, 0, 0, 1);
  }
  
  vec4 compPoint(vec3 materialDiffuse, vec3 materialSpecular, float materialShininess, POINT light)
  {
      vec4 result = vec4(0, 0, 0, 1);
  
      // diffuse
      vec3 L = normalize(matrixView * vec4(light.position, 1) - position).xyz;
      float NdotL = dot(L, normal.xyz);
      if (NdotL &gt; 0)
          result += vec4(light.diffuse * materialDiffuse, 1) * NdotL;
  
      // specular
      vec3 V = normalize(-position.xyz);
      vec3 R = reflect(-L, normal.xyz);
      float RdotV = dot(R, V);
      if (NdotL &gt; 0 &amp;&amp; RdotV &gt; 0)
          result += vec4(light.specular * materialSpecular * pow(RdotV, materialShininess), 1);
  
      //attentuation
      float dist = length(matrixView * vec4(light.position, 1) - position); 
      float att = 1 / (att_quadratic * dist * dist); 
  
      return result * att;
  }
  
  void main(void) 
  {
      // calculate position &amp; normal
      position = matrixModelView * vec4(aVertex, 1.0);
      gl_Position = matrixProjection * position;
      normal = vec4(normalize(mat3(matrixModelView) * aNormal), 1);
  
      // calculate texture coordinate
      texCoord = aTexCoord;
  
      // calculate the colour
      color = vec4(0, 0, 0, 0);
  
      // ambient light
      color += compAmbient(materialAmbient, lightAmbient);
  
      // directional lights
      color += compDirectional(materialDiffuse, lightDir);
  
      // point lights
      if (lightPoint1.on == 1 &amp;&amp; lightPoint1.frag == 0)
          color += compPoint(materialDiffuse, materialSpecular, materialShininess, lightPoint1);
      if (lightPoint2.on == 1 &amp;&amp; lightPoint2.frag == 0)
          color += compPoint(materialDiffuse, materialSpecular, materialShininess, lightPoint2);
      if (lightPoint3.on == 1 &amp;&amp; lightPoint3.frag == 0)
          color += compPoint(materialDiffuse, materialSpecular, materialShininess, lightPoint3);
  
      // calculation of the gravelFactor:
      // 0 outside the 8-unit radius from the center
      // 1 within 7 units from the centre
      // between 0 and 1 at the border zone
      gravelFactor = clamp(-length(aVertex.xz) + 8, 0, 1);
  }
  </code></pre>
  
  <p>Fragment Shader:</p>
  
  <pre><code>// input variables
  in vec4 color;
  in vec4 position;
  in vec4 normal;
  in vec2 texCoord;
  in float gravelFactor;
  
  // output variable
  out vec4 outColor;
  
  // uniforms - material parameters
  uniform vec3 materialAmbient;
  uniform vec3 materialDiffuse;
  uniform vec3 materialSpecular;
  uniform float materialShininess;
  
  uniform float att_quadratic = 0.1;
  
  // This uniform variable may be used to take different actions for the terrain and not-terrain
  uniform int terrain;
  
  // view matrix (needed for lighting)
  uniform mat4 matrixView;
  
  struct POINT
  {   int on;
      int frag;
      vec3 position;
      vec3 diffuse;
      vec3 specular;
  };
  
  uniform POINT lightPoint1, lightPoint2, lightPoint3;
  
  vec4 compPoint(vec3 materialDiffuse, vec3 materialSpecular, float materialShininess, POINT light)
  {
      vec4 result = vec4(0, 0, 0, 1);
  
      // diffuse
      vec3 L = normalize(matrixView * vec4(light.position, 1) - position).xyz;
      float NdotL = dot(L, normal.xyz);
      if (NdotL &gt; 0)
          result += vec4(light.diffuse * materialDiffuse, 1) * NdotL;
  
      // specular
      vec3 V = normalize(-position.xyz);
      vec3 R = reflect(-L, normal.xyz);
      float RdotV = dot(R, V);
      if (NdotL &gt; 0 &amp;&amp; RdotV &gt; 0)
          result += vec4(light.specular * materialSpecular * pow(RdotV, materialShininess), 1);
  
      //attentuation
      float dist = length(matrixView * vec4(light.position, 1) - position); 
      float att = 1 / (att_quadratic * dist * dist); 
  
      return result * att;
  }
  
  // Texture Samplers
  uniform sampler2D textureGrass;
  uniform sampler2D textureGravel;
  uniform sampler2D texture;
  uniform sampler2D bumpmap;
  uniform sampler2D textureNormal;
  
  vec4 bump_normal = texture(textureNormal, texCoord.st) * 2 - 1; 
  
  void main(void) 
  {
      outColor = color;
  
      if (lightPoint1.on == 1 &amp;&amp; lightPoint1.frag == 1)
          outColor += compPoint(materialDiffuse, materialSpecular, materialShininess, lightPoint1);
      if (lightPoint2.on == 1 &amp;&amp; lightPoint2.frag == 1)
          outColor += compPoint(materialDiffuse, materialSpecular, materialShininess, lightPoint2);
      if (lightPoint3.on == 1 &amp;&amp; lightPoint3.frag == 1)
          outColor += compPoint(materialDiffuse, materialSpecular, materialShininess, lightPoint3);
  
      if (terrain == 1)
      {
          // Rendering Terrain
          // Terrain is a mix of the Grass and Gravel texture
          outColor *= mix(texture(textureGrass, texCoord.st), texture(textureGravel, texCoord.st), gravelFactor);
      }
      else
      {
          outColor *= texture(texture, texCoord.st) + bump_normal;
      }
  }
  </code></pre>
  
  <p>And the declaration of my point lights:</p>
  
  <pre><code>//setup point light1
  glUniform1i(glGetUniformLocation(idProg, "lightPoint1.on"), 1);
  glUniform1i(glGetUniformLocation(idProg, "lightPoint1.frag"), 1);
  glUniform3f(glGetUniformLocation(idProg, "lightPoint1.position"), 0, 3.1, 0.0);
  glUniform3f(glGetUniformLocation(idProg, "lightPoint1.diffuse"), 1.0, 0.0, 0.0);
  glUniform3f(glGetUniformLocation(idProg, "lightPoint1.specular"),  1.0, 0.0, 0.0);
  </code></pre>
  
  <p>What would be the best way to approach this problem? Should the position of the light be changed within the main code or within the shaders? How could I do this?</p>