title: Multiple [in] attributes in shader - OpenGL
body: <p>I'm to learn OpenGL 4 and now I working with textures. I would like to apply a texture to a sphere, and my vertex shader looks like this:</p>
  
  <pre><code>#version 410
  
  in vec4 vPosition;
  in vec2 texCoord;
  
  uniform mat4 mvpMatrix;
  uniform mat4 mvMatrix;
  uniform mat3 normalMatrix;
  uniform vec3 vLightPosition;
  
  smooth out vec3 vVaryingNormal;
  smooth out vec3 vVaryingLightDir;
  smooth out vec2 uvCoord;
  
  void main (void)
  {
      uvCoord = texCoord;
      vec3 vNormal = vPosition.xyz / vPosition.w;
      vVaryingNormal = normalMatrix * vNormal;
      vec4 vPosition4 = mvMatrix * vPosition;
      vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
      vVaryingLightDir = normalize(vLightPosition - vPosition3);
      gl_Position = mvpMatrix * vPosition;
  }
  </code></pre>
  
  <p>After defining the coordinates and triangulation indexes of a sphere, I build a VAO with the following code:</p>
  
  <pre><code>void SphereShaderProgram::BuildVAO()
  {
      // Generate and bind the vertex array object
      glGenVertexArrays(1, &amp;_vao);
      glBindVertexArray(_vao);
  
      // Generate and bind the vertex buffer object
      glGenBuffers(1, &amp;_vbo);
      glBindBuffer(GL_ARRAY_BUFFER, _vbo);
      glBufferData(GL_ARRAY_BUFFER, _sphereCoordinates.size() * sizeof(float), &amp;_sphereCoordinates[0], GL_STATIC_DRAW);
  
      // Generate and bind the index buffer object
      glGenBuffers(1, &amp;_ibo);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, _sphereIndexes.size() * sizeof(unsigned int), &amp;_sphereIndexes[0], GL_STATIC_DRAW);
  
      // Generate and bind texture
      _texture = LoadTexture("ball.bmp");
  
      LoadAttributeVariables();
  
      glBindVertexArray(0);
  }
  
  GLuint ProgramManager::LoadTexture(const char* imagepath)
  {    
      unsigned int width, height;
      unsigned char * data = LoadBMP(imagepath, &amp;width, &amp;height);
  
      GLuint textureID;
      glGenTextures(1, &amp;textureID);
      glBindTexture(GL_TEXTURE_2D, textureID);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  
      return textureID;
  }
  </code></pre>
  
  <p>To load the attributes, I did the following (before using texture):</p>
  
  <pre><code>void SphereShaderProgram::LoadAttributeVariables()
  {
      // Vertex Attributes
      GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
      glEnableVertexAttribArray(VertexPosition_location);
      glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
  }
  </code></pre>
  
  <p>Now, however, I have an array (<code>_sphereTexCoords</code>) which contains the texture coordinates and I don't really know how to pass it to the vertex shader as the vertex coordinates are passed. Do I have to create another VBO? I though of doing something like this:</p>
  
  <pre><code>GLuint TextureCoord_Location = glGetAttribLocation(GetProgramID(), "texCoord");
  glEnableVertexAttribArray(TextureCoord_Location);
  glVertexAttribPointer(TextureCoord_Location, 2, GL_FLOAT, GL_FALSE, 0, 0);
  </code></pre>
  
  <p>But I don't really know how to specify that this is related to the <code>_sphereTexCoords</code> array.</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>I tried this, but it didn't work.</p>
  
  <pre><code>void SphereShaderProgram::BuildVAO()
  {
      // Generate and bind the vertex array object
      glGenVertexArrays(1, &amp;_vao);
      glBindVertexArray(_vao);
  
      // Generate and bind the vertex buffer object
      glGenBuffers(2, _vbo);
      glBindBuffer(GL_ARRAY_BUFFER, _vbo[0]);
      glBufferData(GL_ARRAY_BUFFER, _sphereCoordinates.size() * sizeof(float), &amp;_sphereCoordinates[0], GL_STATIC_DRAW);
      glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
      glBufferData(GL_ARRAY_BUFFER, _textureCoordinates.size() * sizeof(float), &amp;_textureCoordinates[0], GL_STATIC_DRAW);
  
      // Generate and bind the index buffer object
      glGenBuffers(1, &amp;_ibo);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, _sphereIndexes.size() * sizeof(unsigned int), &amp;_sphereIndexes[0], GL_STATIC_DRAW);
  
      // Generate and bind texture
      _texture = LoadTexture("ball.bmp");
  
      LoadAttributeVariables();
  
      glBindVertexArray(0);
  }
  
  void SphereShaderProgram::LoadAttributeVariables()
  {
      // Vertex Attributes
      GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
      glEnableVertexAttribArray(VertexPosition_location);
      glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
  
      GLuint TextureCoord_Location = glGetAttribLocation(GetProgramID(), "texCoord");
      glEnableVertexAttribArray(TextureCoord_Location);
      glVertexAttribPointer(TextureCoord_Location, 2, GL_FLOAT, GL_FALSE, 0, 0);
  }
  </code></pre>
  
  <p>I get an error when binding the program.</p>