title: How do you handle multiple textures in an OpenGL indexed buffer array for use with a data-shader?
body: <p>I'm attempting to implement <a href="http://graphics.cs.williams.edu/papers/EdgesNPAR04/index.html" rel="nofollow noreferrer">this paper</a>. I've have most of it down, but the part about sending arbitrary, non-geometric data to the shader for use in determining and displaying geometric edges is causing me problems. I've managed to successfully send most of my data just fine using what I know of VBOs. However, I need to send a large amount of data, which necessitates the use of multiple texture coordinates.</p>
  
  <p>I've already implemented several variations of what I believe to be the correct way of setting up multiple sets of texture coordinates, and followed the instructions of many forum posters. No solutions work thus far.</p>
  
  <p>For context, the program is sending 4 nearly identical copies of a set of 4 vertices, 2 normal vectors, a float, and an integer (stored as a float) for each unique edge in the model. I've laid out the data like this:</p>
  
  <pre><code>v0 is stored in gl_Vertex (vec3)
  v1 is stored in gl_Color (vec3)
  v2 is stored in gl_MultiTexCoord0 (vec3)
  v3 is stored in gl_MultiTexCoord1 (vec3)
  n0 is stored in gl_Normal (vec3)
  n1 is stored in gl_SecondaryColor (vec3)
  r and i are stored in gl_MultiTexCoord2 (vec2)
  </code></pre>
  
  <p>The only difference between the 4 copies is the i value, which helps determine how to organize the vertices if and when a drawable edge is found.</p>
  
  <p>As you can see, I need at least 3 texture coordinates. I was able to get the first one working (gl_MultiTexCoord0) just fine, but any following texture coordinates, though on the graphics card, appear to have uncontrollable behavior, sometimes working, but usually not.</p>
  
  <p>My rendering function used to look like this:</p>
  
  <pre><code>void Mesh::RenderLineEdgesGPU()
  {
      // Enable client state
      glEnableClientState(GL_VERTEX_ARRAY);
      glEnableClientState(GL_NORMAL_ARRAY);
      glEnableClientState(GL_COLOR_ARRAY);
      glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  
      // Turn on edge shader
      edgeProgram.Activate();
  
      // Link buffers
      // v0
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
      glVertexPointer(3, GL_FLOAT, 0, 0);
  
      // v1
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
      glColorPointer(3, GL_FLOAT, 0, 0);
  
      // v2
      glClientActiveTextureARB(GL_TEXTURE0_ARB);
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
      glTexCoordPointer(3, GL_FLOAT, 0, 0);
  
      // v3
      glClientActiveTextureARB(GL_TEXTURE1_ARB);
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
      glTexCoordPointer(3, GL_FLOAT, 0, 0);
  
      // n0
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
      glNormalPointer(GL_FLOAT, 0, 0);
  
      // n1
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
      glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
  
      // r and i
      glClientActiveTextureARB(GL_TEXTURE2_ARB);
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
      glTexCoordPointer(2, GL_FLOAT, 0, 0);
  
      // Indicies
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
  
      // Draw
      glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
  
      // Turn off edge shader
      edgeProgram.Deactivate();
  
      // Disable client state
      glDisableClientState(GL_VERTEX_ARRAY);
      glDisableClientState(GL_NORMAL_ARRAY);
      glDisableClientState(GL_COLOR_ARRAY);
      glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  }
  </code></pre>
  
  <p>This was my original one. It definitely works for v0, v1, and v2. It appears to work for "r and i", but that could be an illusion. I don't have the ability to test n0 or n1 yet. v3 definitely DOES NOT work. As you can see, I'm drawing them as points, which tells me if they are there or not (via the shader). v0, v1, and v2 are all there. Attempting to do the same for v3 yields either a single point at the origin or nothing at all.</p>
  
  <p>After looking at suggestions online, here's my new setup:</p>
  
  <pre><code>void Mesh::RenderLineEdgesGPU()
  {
      // Enable client state
      glEnableClientState(GL_VERTEX_ARRAY);
      glEnableClientState(GL_NORMAL_ARRAY);
      glEnableClientState(GL_COLOR_ARRAY);
      glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
  
      // Turn on edge shader
      edgeProgram.Activate();
  
      // Link buffers
      // v0
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
      glVertexPointer(3, GL_FLOAT, 0, 0);
  
      // v1
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
      glColorPointer(3, GL_FLOAT, 0, 0);
  
      // v2
      glClientActiveTextureARB(GL_TEXTURE0_ARB);
  
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
      glActiveTextureARB(GL_TEXTURE0_ARB);
      glEnable(GL_TEXTURE_2D);
  
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
      glTexCoordPointer(3, GL_FLOAT, 0, 0);
  
      glDisable(GL_TEXTURE_2D);
      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  
      // v3
      glClientActiveTextureARB(GL_TEXTURE1_ARB);
  
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
      glActiveTextureARB(GL_TEXTURE1_ARB);
      glEnable(GL_TEXTURE_2D);
  
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
      glTexCoordPointer(3, GL_FLOAT, 0, 0);
  
      glDisable(GL_TEXTURE_2D);
      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  
      // n0
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
      glNormalPointer(GL_FLOAT, 0, 0);
  
      // n1
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
      glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
  
      // r and i
      glClientActiveTextureARB(GL_TEXTURE2_ARB);
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
      glTexCoordPointer(2, GL_FLOAT, 0, 0);
  
      // Indicies
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
  
      // Draw
      glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
  
      // Turn off edge shader
      edgeProgram.Deactivate();
  
      // Disable client state
      glDisableClientState(GL_VERTEX_ARRAY);
      glDisableClientState(GL_NORMAL_ARRAY);
      glDisableClientState(GL_COLOR_ARRAY);
      glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
  }
  </code></pre>
  
  <p>Notice how I've done the <code>glEnableClientState</code> / <code>glDisableClientState</code> calls around the actual "loading" of each texture coordinate list. I also use <code>glActiveTextureARB</code> and <code>glEnable(GL_TEXTURE_2D)</code>. While I think I might understand why <code>glActiveTextureARB</code> is needed here, the other one baffles me. According to the <a href="http://www.opengl.org/wiki/GLSL_:_common_mistakes#Enable_Or_Not_To_Enable" rel="nofollow noreferrer">GLSL Common Mistakes page</a>, you're not supposed to use <code>glEnable(GL_TEXTURE_2D)</code> when you make your own shaders, since the use of shaders ignores this call anyway.</p>
  
  <p>So that's it. I've gotten this far without being able to find any tutorials specifically addressing how to send non-texture coordinate data in texture coordinates. Perhaps if someone knows a tutorial on that, my problem would be alleviated. Thanks for your time!</p>