title: Textures appear pure black, unless I pass an invalid value to texture uniform location
body: <p>My program has been working perfectly so far, but it turns out that I've been lucky. I began doing some cleanup of the shader, because it was full of experimental stuff, and I had the following line at the end of the fragment shader:</p>
  
  <pre><code>gl_FragColor = final_color * (texture2D(tex, gl_TexCoord[0].st)*1.0 + texture2D(tex2, gl_TexCoord[0].st)*1.0);
  </code></pre>
  
  <p>I attempted to clean it up and I had the following declared at the top:</p>
  
  <pre><code>uniform sampler2D tex, tex2;
  </code></pre>
  
  <p>Changing these lines to:</p>
  
  <pre><code>gl_FragColor = final_color * texture2D(tex, gl_TexCoord[0].st;
  </code></pre>
  
  <p>and</p>
  
  <pre><code>uniform sampler2D tex;
  </code></pre>
  
  <p>actually broke the program (black screen), even though I am doing</p>
  
  <pre><code>GLuint tex_loc = glGetUniformLocation(shader_prog_id_, "tex");
  glUniform1i(tex_loc, texture_id_);
  </code></pre>
  
  <p>in my main code. I'm sure it's a texture issue and not a glsl compiler error, because I can add <code>1.0</code> to the output and end up with a white silhouette of my mesh.</p>
  
  <p>The strangeness begins when I change the lines in my shader to:</p>
  
  <pre><code>gl_FragColor = final_color * texture2D(tex2, gl_TexCoord[0].st;
  </code></pre>
  
  <p>and</p>
  
  <pre><code>uniform sampler2D tex2;
  </code></pre>
  
  <p>but still retrieve the location for <code>tex</code>. The program works as it always has, even though inspecting the value of <code>tex_loc</code> in the debugger indicates an error. I'm not happy doing this, and now that I'm trying to load multiple textures, it will cause bigger headaches down the line.</p>
  
  <p>I'm using VBOs, in interleaved format, to render the geometry. I'm passing in the vertex position, normal and texcoord this way.</p>
  
  <p>There are other questions with the "black texture" issue, but they're using immediate mode calls and setting the wrong texture state. I tried changing the texture unit before supplying the arrays, with no success.</p>
  
  <p>Here is as much relevant code as possible from the main program:</p>
  
  <pre><code>void MeshWidget::draw() {
  
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslatef(0.0f, 0.0f, -4.0f + zoom_factor_);
      glRotatef(rotX, 1.0f, 0.0f, 0.0f);
      glRotatef(rotY, 0.0f, 1.0f, 0.0f);
      glRotatef(rotZ, 0.0f, 0.0f, 1.0f);
  
      // Auto centre mesh based on vertex bounds.
      glTranslatef(-x_mid_, -y_mid_, -z_mid_);
  
      glDrawElements(GL_TRIANGLES, mesh_.num_indices, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));   //The starting point of the IBO
  }
  
  
  void MeshWidget::openMesh(const string&amp; filename) {
  
      if (mesh_filename_ != filename) {
  
          clearMeshData(mesh_);
  
          glDeleteBuffersARB(1, &amp;VertexVBOID);
          glDeleteBuffersARB(1, &amp;IndexVBOID);
  
          ReadMsh(mesh_, filename);
  
          // Create buffer objects here.
          glGenBuffersARB(1, &amp;VertexVBOID);
          glBindBufferARB(GL_ARRAY_BUFFER, VertexVBOID);
          glBufferDataARB(GL_ARRAY_BUFFER, sizeof(VertexAttributes)*mesh_.num_vertices, &amp;mesh_.vertices[0], GL_STATIC_DRAW);
  
          glGenBuffersARB(1, &amp;IndexVBOID);
          glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
          glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint16_t)*mesh_.num_indices, &amp;mesh_.indices[0], GL_STATIC_DRAW);
  
          glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
          glEnableClientState(GL_VERTEX_ARRAY);
          glVertexPointer(3, GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(0));   //The starting point of the VBO, for the vertices
          glEnableClientState(GL_NORMAL_ARRAY);
          glNormalPointer(GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(12));   //The starting point of normals, 12 bytes away
          glClientActiveTexture(GL_TEXTURE0);
          glEnableClientState(GL_TEXTURE_COORD_ARRAY);
          glTexCoordPointer(2, GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(24));   //The starting point of texcoords, 24 bytes away
  
          glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
  
          if (startup_done_) updateGL();
      }
  }
  
  void MeshWidget::openTexture(const string&amp; filename) {
  
      size_t dot = filename.find_last_of('.');
      string ext(filename, dot, filename.size()); // 3rd parameter should be length of new string, but is internally clipped to end.
  
      glActiveTexture(GL_TEXTURE0);
      glClientActiveTexture(GL_TEXTURE0);
      glDeleteTextures(1, &amp;texture_id_);
      glGenTextures(1, &amp;texture_id_);
      glBindTexture(GL_TEXTURE_2D, texture_id_);
  
      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  
      if (ext == ".dds") {
          if (GLEE_EXT_texture_compression_s3tc) {
  
              texture_id_ = SOIL_load_OGL_texture(filename.c_str(), SOIL_LOAD_AUTO, texture_id_, SOIL_FLAG_DDS_LOAD_DIRECT);
              // SOIL takes care of calling glTexParams, glTexImage2D, etc.
              yflip_texture_ = true;
  
              } else {
                  //std::cout &lt;&lt; "S3TC not supported on this graphics hardware." &lt;&lt; std::endl;
                  // TODO: Error message in status bar?
              }
  
      } else {
  
          QImage tex(filename.c_str());
          tex = QGLWidget::convertToGLFormat(tex);
  
          glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
  
          yflip_texture_ = false;
  
      }
  
      updateUniforms();
  
      if (startup_done_) updateGL();
  }
  
  void MeshWidget::updateUniforms() {
  
      GLuint texture_flip_uniform = glGetUniformLocation(shader_prog_id_, "yflip");
      glUniform1f(texture_flip_uniform, float(yflip_texture_ * 1.0f));
  
      GLuint tex_loc = glGetUniformLocation(shader_prog_id_, "tex");
      glUniform1i(tex_loc, texture_id_);
  }
  </code></pre>
  
  <p>And my shaders (there's still some junk in here because I was experimenting, but nothing that affects the output):</p>
  
  <pre><code>varying vec3 normal, lightDir, eyeVec;
  uniform float yflip;
  
  void main()
  {   
      normal = gl_NormalMatrix * gl_Normal;
  
      vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
  
      lightDir = vec3(gl_LightSource[0].position.xyz - vVertex);
      eyeVec = -vVertex;
  
      gl_TexCoord[0].x = gl_MultiTexCoord0.x;
      gl_TexCoord[1].x = gl_MultiTexCoord1.x;
  
      if (yflip == 1.0) {
          gl_TexCoord[0].y = 1 - gl_MultiTexCoord0.y;
          gl_TexCoord[1].y = 1 - gl_MultiTexCoord1.y;
      } else {
          gl_TexCoord[0].y = gl_MultiTexCoord0.y;
          gl_TexCoord[1].y = gl_MultiTexCoord1.y;
      }
  
      gl_Position = ftransform();
  }
  </code></pre>
  
  <p>fragment shader:</p>
  
  <pre><code>varying vec3 normal, lightDir, eyeVec;
  uniform sampler2D tex2;
  
  void main (void)
  {
  
      vec4 texel = texture2D(tex2, gl_TexCoord[0].st);
  
      vec4 final_color =
  (gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) + 
  (gl_LightSource[0].ambient * gl_FrontMaterial.ambient);
  
      vec3 N = normalize(normal);
      vec3 L = normalize(lightDir);
  
      float lambertTerm = dot(N,L);
  
      if(lambertTerm &gt; 0.0)
      {
          final_color += gl_LightSource[0].diffuse * 
                     gl_FrontMaterial.diffuse * 
                     lambertTerm; 
  
          vec3 E = normalize(eyeVec);
          vec3 R = reflect(-L, N);
          float specular = pow( max(dot(R, E), 0.0), 
                       gl_FrontMaterial.shininess );
          final_color += gl_LightSource[0].specular * 
                     gl_FrontMaterial.specular * 
                     specular;    
      }
  
      gl_FragColor = final_color * texel;
  }
  </code></pre>