title: Textures not working (Black Textures) - OpenGL + GLSL
body: <p>I am trying to detect silhouette edges and render some textures (varies based on the diffuse term) on these edges using OpenGL and shaders. I am rendering a quad using the geometry shader and also assign the texture coordinates here. In the fragment shader, i am trying to use the diffuse term calculated in vertex shader to render different textures based on diffTerm's value. There are two issues with my code.</p>
  
  <p>1) The diffuse term should vary from (-1,1) but it seems to be stuck at 0 when i rotate the model and it reaches negative values at certain positions.</p>
  
  <p>2) The textures are always black and I cant seem to find out what is causing this issue.</p>
  
  <p>"MeshViewer.cpp" - The main file</p>
  
  <pre><code>Mesh* mesh;
  GLuint* texID = new GLuint[5];
  float rotn_x = 0.0, rotn_y = 0.0, fov;
  GLuint matrixLoc1, matrixLoc2, matrixLoc3,texLoc1, texLoc2, texLoc3, texLoc4, texLoc5;
  float cam_near, cam_far;    //Near and far planes of the camera
  const float PI = 3.14159265f;
  glm::mat4 view;   //View and projection matrices
  
  void loadTextures()
  {
  glGenTextures(5, texID);   //Generate 1 texture ID
  glActiveTexture(GL_TEXTURE0);  //Texture unit 0
  glBindTexture(GL_TEXTURE_2D, texID[0]);
  loadTGA("Pencil0.tga");
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  
  glActiveTexture(GL_TEXTURE1);  //Texture unit 0
  glBindTexture(GL_TEXTURE_2D, texID[1]);
  loadTGA("Pencil1.tga");
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  
  glActiveTexture(GL_TEXTURE2);  //Texture unit 0
  glBindTexture(GL_TEXTURE_2D, texID[2]);
  loadTGA("Pencil2.tga");
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  
  glActiveTexture(GL_TEXTURE3);  //Texture unit 0
  glBindTexture(GL_TEXTURE_2D, texID[3]);
  loadTGA("Brick.tga");
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  
  glActiveTexture(GL_TEXTURE4);  //Texture unit 0
  glBindTexture(GL_TEXTURE_2D, texID[4]);
  loadTGA("Brick.tga");
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  }
  void initialise()
  {
  // --- Mesh object ---
  GLuint lgtLoc;
  mesh = new Mesh();
  if(!mesh-&gt;loadMeshOFF("Camel.off")) cout &lt;&lt; "Error reading mesh data file." &lt;&lt; endl;
  
  //  --- Camera parameters ---
  float win_width = (mesh-&gt;_xmax - mesh-&gt;_xmin) * 1.5f;
  float win_height = (mesh-&gt;_ymax - mesh-&gt;_ymin) * 1.5f;
  if(win_width &gt; win_height)  win_height = win_width;    //Maintain aspect ratio = 1
  cam_near = 2*(mesh-&gt;_zmax) - mesh-&gt;_zmin;
  cam_far =  2*(mesh-&gt;_zmin) - mesh-&gt;_zmax;
  float cam_posx = (mesh-&gt;_xmax + mesh-&gt;_xmin) * 0.5f;
  float cam_posy = (mesh-&gt;_ymax + mesh-&gt;_ymin) * 0.5f;
  float cam_posz = cam_near + win_height;
  fov = 27.0f;                                //Approx. atan(0.5)
  
  // --- Uniform locations ---
  GLuint program = createShaderProg("MeshViewer.vert", "MeshViewer.frag", "MeshViewer.geom");
  matrixLoc1 = glGetUniformLocation(program, "mvMatrix");
  matrixLoc2 = glGetUniformLocation(program, "mvpMatrix");
  matrixLoc3 = glGetUniformLocation(program, "norMatrix");
  lgtLoc = glGetUniformLocation(program, "lightPos");
  
  GLint lineWidth = glGetUniformLocation(program, "HalfWidth");
  if (lineWidth &gt; -1)
      glUniform1f(lineWidth, 0.005f);
  GLint overhangLength = glGetUniformLocation(program, "OverhangLength");
  if (overhangLength &gt; -1)
      glUniform1f(overhangLength, 0.15f);
  
  texLoc1 = glGetUniformLocation (program, "tex1"); 
  glUniform1i(texLoc1, 0);
  texLoc2 = glGetUniformLocation (program, "tex2"); 
  glUniform1i(texLoc2, 1);
  texLoc3 = glGetUniformLocation (program, "tex3"); 
  glUniform1i(texLoc3, 2);
  texLoc4 = glGetUniformLocation (program, "tex4"); 
  glUniform1i(texLoc4, 3);
  texLoc5 = glGetUniformLocation (program, "tex5"); 
  glUniform1i(texLoc5, 4);
  
  
  view = glm::lookAt(glm::vec3(cam_posx, cam_posy, cam_posz), glm::vec3(cam_posx, cam_posy, 0.0),         glm::vec3(0.0, 1.0, 0.0)); //view matrix
  glm::vec4 light = glm::vec4(100.0, 50.0, 100.0, 1.0);             //Light's position
  glm::vec4 lightEye = view*light;     //Light position in eye coordinates
  glUniform4fv(lgtLoc, 1, &amp;lightEye[0]);
  
  // --- OpenGL  ---
  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);       
  glEnable(GL_DEPTH_TEST);
  
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);   //Wireframe
  mesh-&gt;setColor(0, 0, 1);                    //Mesh color = blue.
  
  mesh-&gt;createVAO();   //Create buffer objects for the mesh
  }
  
  
  void display()  
  {
  glm::mat4 proj;
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
  
  glm::mat4 matrix = glm::mat4(1.0);
  matrix = glm::rotate(matrix, rotn_x, glm::vec3(1.0, 0.0, 0.0));  //rotation about x
  matrix = glm::rotate(matrix, rotn_y, glm::vec3(0.0, 1.0, 0.0));  //rotation about y
  glm::mat4 prodMatrix1 = view*matrix;        //Model-view matrix
  proj = glm::perspective(fov, 1.0f, cam_near, cam_far);  //perspective projection matrix
  glm::mat4 prodMatrix2 = proj*prodMatrix1;   //The model-view-projection transformation
  glm::mat4 invMatrix = glm::inverse(prodMatrix1);  //Inverse of model-view matrix for normal transformation
  glUniformMatrix4fv(matrixLoc1, 1, GL_FALSE, &amp;prodMatrix1[0][0]);
  glUniformMatrix4fv(matrixLoc2, 1, GL_FALSE, &amp;prodMatrix2[0][0]);
  glUniformMatrix4fv(matrixLoc3, 1, GL_TRUE, &amp;invMatrix[0][0]);  //Use transpose matrix here
  
  mesh-&gt;render();
  
  glFlush();
  }
  
  
  void specialKeys(int key, int x, int y)
  {
  if(key == GLUT_KEY_LEFT) rotn_y -= 5.0;
  else if(key == GLUT_KEY_RIGHT) rotn_y += 5.0;
  else if(key == GLUT_KEY_UP) rotn_x -= 5.0;
  else if(key == GLUT_KEY_DOWN) rotn_x += 5.0;
  else if(key == GLUT_KEY_PAGE_UP) fov --;
  else if(key == GLUT_KEY_PAGE_DOWN) fov ++;
  if(fov &lt; 1.0) fov = 1.0;
  else if(fov &gt; 80.0) fov = 80.0;
  glutPostRedisplay();
  }
  
  
  int main(int argc, char** argv)
  {
  glutInit(&amp;argc, argv);
  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize (600, 600); 
  glutInitWindowPosition (20, 10);
  glutCreateWindow ("Mesh Viewer");
  glutInitContextVersion (4, 2);
  glutInitContextProfile ( GLUT_CORE_PROFILE );
  
  if(glewInit() == GLEW_OK)
  {
      cout &lt;&lt; "GLEW initialization successful! " &lt;&lt; endl;
      cout &lt;&lt; " Using GLEW version " &lt;&lt; glewGetString(GLEW_VERSION) &lt;&lt; endl;
  }
  else
  {
      cerr &lt;&lt; "Unable to initialize GLEW  ...exiting." &lt;&lt; endl;
      exit(EXIT_FAILURE);
  }
  initialise ();
  glutDisplayFunc(display); 
  glutSpecialFunc(specialKeys);
  glutMainLoop();
  return 0;
  }
  </code></pre>
  
  <p>Vertex Shader:</p>
  
  <pre><code>#version 330
  
  layout (location = 0) in vec4 position;
  layout (location = 1) in vec3 normal;
  layout (location = 2) in vec3 cols;
  layout (location = 3) in vec2 texC;
  
  uniform mat4 mvMatrix;
  uniform mat4 mvpMatrix;
  uniform mat4 norMatrix;
  uniform vec4 lightPos;
  out float diffTerm;
  out vec4 vColour;
  out float viewTerm;
  out float silhoutte;
  out vec2 TexC;
  
  void main()
  {
  vec4 grey = vec4(0.2, 0.2, 0.2, 1.0);
  vec4 posnEye = mvMatrix * position;
  vec4 normalEye = norMatrix * vec4(normal, 0);
  vec4 lgtVec = normalize(lightPos - posnEye);  
  vec4 viewVec = normalize(vec4(-posnEye.xyz, 0)); 
  float viewTerm = max(dot(viewVec, normalEye),0);
  vec4 material = vec4(cols, 1.0);
  vec4 lgtAmb = grey * material;
  diffTerm = max(dot(lgtVec, normalEye), 0);
  vec4 lgtDiff = material * diffTerm;
  silhoutte = dot(viewVec, normalEye);
  gl_Position = mvpMatrix * position;
  vColour = vec4(cols, 1);
  TexC = texC;
  }
  </code></pre>
  
  <p>Geometry Shader:</p>
  
  <pre><code>#version 430 core
  
  
  layout(triangles_adjacency) in;
  layout(triangle_strip, max_vertices = 6) out;
  in vec2 texC[];
  out vec2 TexCoord;
  in vec4 vColour[];
  out vec4 colorv;
  in float viewTerm[];
  out float viewTermg;
  in float diffTerm[];
  out float diffTermg;
  in vec2 TexC[];
  out vec2 TexCg;
  uniform float HalfWidth;
  uniform float OverhangLength;
  out float gDist;
  out vec3 gSpine;
  
  bool IsFront(vec3 A, vec3 B, vec3 C)
  {
  float area = (A.x * B.y - B.x * A.y) + (B.x * C.y - C.x * B.y) + (C.x * A.y - A.x * C.y);
  return area &gt; 0;
  }
  
  void EmitEdge(vec3 P0, vec3 P1)
  {
  vec3  E = OverhangLength * vec3(P1.xy - P0.xy, 0);
  vec2  V = normalize(E.xy);
  vec3  N = vec3(-V.y, V.x, 0) * 0.005;
  vec3  S = -N;
  float D = HalfWidth;
  
  gSpine = P0;
  gl_Position = vec4(P0 + S - E, 1); gDist = +D; TexCoord=vec2(0.0,0.0); colorv = vColour[0];     EmitVertex();
  gl_Position = vec4(P0 + N - E, 1); gDist = -D; TexCoord=vec2(1.0,0.0); colorv = vColour[1]; EmitVertex();
  gSpine = P1;
  gl_Position = vec4(P1 + S + E, 1); gDist = +D; TexCoord=vec2(1.0,1.0); colorv = vColour[0]; EmitVertex();
  gl_Position = vec4(P1 + N + E, 1); gDist = -D; ; TexCoord=vec2(0.0,1.0); EmitVertex();
  EndPrimitive();
  }
  
  void main()
  {
  vec3 v0 = gl_in[0].gl_Position.xyz / gl_in[0].gl_Position.w;
  vec3 v1 = gl_in[1].gl_Position.xyz / gl_in[1].gl_Position.w;
  vec3 v2 = gl_in[2].gl_Position.xyz / gl_in[2].gl_Position.w;
  vec3 v3 = gl_in[3].gl_Position.xyz / gl_in[3].gl_Position.w;
  vec3 v4 = gl_in[4].gl_Position.xyz / gl_in[4].gl_Position.w;
  vec3 v5 = gl_in[5].gl_Position.xyz / gl_in[5].gl_Position.w;
  
  if (IsFront(v0, v2, v4)) {
      if (!IsFront(v0, v1, v2)) EmitEdge(v0, v2);
      //if (!IsFront(v2, v3, v4)) EmitEdge(v2, v4);
      //if (!IsFront(v0, v4, v5)) EmitEdge(v4, v0);
  } 
  
  }
  </code></pre>
  
  <p>Fragment Shader:</p>
  
  <pre><code>#version 330
  
  in vec4 vColourg;
  in float diffTermg;
  in float silhoutte;
  in vec2 TexCg;
  in vec2 TexCoord;
  uniform sampler2D tex1;
  uniform sampler2D tex2;
  uniform sampler2D tex3;
  uniform sampler2D tex4;
  uniform sampler2D tex5;
  
  void main()
  {
  
  
  
  vec4 texColor1 = texture(tex1, TexCoord);
  vec4 texColor2 = texture(tex2, TexCoord);
  vec4 texColor3 = texture(tex3, TexCoord);
  vec4 texColor4 = texture(tex4, TexCoord);
  vec4 texColor5 = texture(tex5, TexCoord);
  
  vec4 blue = vec4(0.0,0.0,1.0,0.0);
  vec4 red = vec4(1.0,0.0,0.0,0.0);
  vec4 yellow = vec4(1.0,1.0,0.0,0.0);
  
  
  if (diffTermg&lt;0)
  {
  gl_FragColor = blue;
  }
  else if (diffTermg ==0)
  {
  gl_FragColor = texColor5;
  }
  else if (diffTermg &gt; 0 &amp;&amp; diffTermg &lt; 0.2)
  gl_FragColor = yellow;
  else if (diffTermg &gt; 100)
  gl_FragColor = blue;
  
  }
  </code></pre>
  
  <p><strong>EDIT:</strong>
  Shader.h</p>
  
  <pre><code>GLuint loadShader(GLenum shaderType, string filename)
  {
  ifstream shaderFile(filename.c_str());
  if(!shaderFile.good()) cout &lt;&lt; "Error opening shader file." &lt;&lt; endl;
  stringstream shaderData;
  shaderData &lt;&lt; shaderFile.rdbuf();
  shaderFile.close();
  string shaderStr = shaderData.str();
  const char* shaderTxt = shaderStr.c_str();
  
  GLuint shader = glCreateShader(shaderType);
  glShaderSource(shader, 1, &amp;shaderTxt, NULL);
  glCompileShader(shader);
  GLint status;
  glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;status);
  if (status == GL_FALSE)
  {
      GLint infoLogLength;
      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &amp;infoLogLength);
      GLchar *strInfoLog = new GLchar[infoLogLength + 1];
      glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
      const char *strShaderType = NULL;
      cerr &lt;&lt;  "Compile failure in shader: " &lt;&lt; strInfoLog &lt;&lt; endl;
      delete[] strInfoLog;
  }
  return shader;
  }
  
  GLuint createShaderProg(string vertShader, string fragShader, string geomShader)
  {
  GLuint shaderv = loadShader(GL_VERTEX_SHADER, vertShader);
  GLuint shaderf = loadShader(GL_FRAGMENT_SHADER, fragShader);
  GLuint shaderg = loadShader(GL_GEOMETRY_SHADER, geomShader);
  
  GLuint program = glCreateProgram();
  glAttachShader(program, shaderv);
  glAttachShader(program, shaderf);
  glAttachShader(program, shaderg);
  glLinkProgram(program);
  
  GLint status;
  glGetProgramiv (program, GL_LINK_STATUS, &amp;status);
  if (status == GL_FALSE)
  {
      GLint infoLogLength;
      glGetProgramiv(program, GL_INFO_LOG_LENGTH, &amp;infoLogLength);
      GLchar *strInfoLog = new GLchar[infoLogLength + 1];
      glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
      fprintf(stderr, "Linker failure: %s\n", strInfoLog);
      delete[] strInfoLog;
      program = 0;
  }
  glUseProgram(program);
  return program;
  }
  </code></pre>
  
  <p>loadTGA.h</p>
  
  <pre><code>void loadTGA(string filename)
  {
  char id, cmap, imgtype, bpp, c_garb;
  char* imageData, temp;
  short int s_garb, wid, hgt;
  int nbytes, size, indx;
  ifstream file( filename.c_str(), ios::in | ios::binary);
  if(!file)
  {
      cout &lt;&lt; "*** Error opening image file: " &lt;&lt; filename.c_str() &lt;&lt; endl;
      exit(1);
  }
  file.read (&amp;id, 1);
  file.read (&amp;cmap, 1);
  file.read (&amp;imgtype, 1);    
  if(imgtype != 2 &amp;&amp; imgtype != 3 )   //2= colour (uncompressed),  3 = greyscale (uncompressed)
  {
      cout &lt;&lt; "*** Incompatible image type: " &lt;&lt; (int)imgtype &lt;&lt; endl;
      exit(1);
  }
  //Color map specification
  file.read ((char*)&amp;s_garb, 2);
  file.read ((char*)&amp;s_garb, 2);
  file.read (&amp;c_garb, 1);
  //Image specification
  file.read ((char*)&amp;s_garb, 2);  //x origin
  file.read ((char*)&amp;s_garb, 2);  //y origin
  file.read ((char*)&amp;wid, 2);     //image width                                   
  file.read ((char*)&amp;hgt, 2);     //image height
  file.read (&amp;bpp, 1);     //bits per pixel
  file.read (&amp;c_garb, 1);  //img descriptor
  nbytes = bpp / 8;           //No. of bytes per pixels
  size = wid * hgt * nbytes;  //Total number of bytes to be read
  imageData = new char[size];
  file.read(imageData, size);
  //cout &lt;&lt; "&gt;&gt;&gt;" &lt;&lt; nbytes &lt;&lt; " " &lt;&lt; wid &lt;&lt; " " &lt;&lt; hgt &lt;&lt; endl;
  if(nbytes &gt; 2)   //swap R and B
  {
      for(int i = 0; i &lt; wid*hgt;  i++)
      {
          indx = i*nbytes;
          temp = imageData[indx];
          imageData[indx] = imageData[indx+2];
          imageData[indx+2] = temp;
      }
  }
  
  switch (nbytes)
  {
       case 1:
           glTexImage2D(GL_TEXTURE_2D, 0, 1, wid, hgt, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, imageData);
           break;
       case 3:
           glTexImage2D(GL_TEXTURE_2D, 0, 3, wid, hgt, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
           break;
       case 4:
           glTexImage2D(GL_TEXTURE_2D, 0, 4, wid, hgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
           break;
   }
   delete imageData;                       
  }
  </code></pre>