title: Problem mapping textures to VBO in OpenGL
body: <p>I'm having trouble getting a texture to map onto geometry properly with OpenGL. In fact I seem to have even broken the colour interpolation that used to work fine. I've created a test case in C99 that uses SDL, GLee and SOIL.</p>
  
  <pre><code>#include &lt;stdbool.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;assert.h&gt;
  
  #include &lt;SDL/SDL.h&gt;
  #include &lt;GL/GLee.h&gt;
  #include &lt;SOIL/SOIL.h&gt;
  
  static const char *vertex_source = " \
  uniform mat4 projection; \
  uniform mat4 view_model; \
   \
  attribute vec2 vertex; \
  attribute vec2 texcoord; \
  attribute vec4 colour; \
   \
  varying vec2 _texcoord; \
   \
  void main() \
  { \
      gl_Position = gl_ModelViewProjectionMatrix * vec4(vertex, 0, 1); \
      _texcoord = texcoord; \
      gl_FrontColor = colour; \
  } ";
  
  static const char *fragment_source = " \
  uniform sampler2D sampler0; \
   \
  varying vec2 _texcoord; \
   \
  void main() \
  { \
      gl_FragColor = texture2D(sampler0, _texcoord) * 0.01 + gl_Color; \
  } ";
  
  typedef struct
  {
      GLfloat position[2];
      GLfloat texcoord[2];
      GLubyte colour[4];
  } Vertex;
  
  static Vertex verts[] = {
          {
              .position = { 1, 1 },
              .texcoord = { 1, 1 },
              .colour = { 255, 0, 0, 255 },
          },
          {
              .position = { -1, 1 },
              .texcoord = { 0, 1 },
              .colour = { 0, 255, 0, 255 },
          },
          {
              .position = { -1, -1 },
              .texcoord = { 0, 0 },
              .colour = { 0, 0, 255, 255 },
          },
          {
              .position = { 1, -1 },
              .texcoord = { 1, 0 },
              .colour = { 255, 255, 0, 255 },
          },
      };
  
  static GLuint vertex, fragment, program, vbo, texture;
  static GLint sampler_loc, vertex_loc, texcoord_loc, colour_loc;
  
  static void init()
  {
      SDL_Init(SDL_INIT_EVERYTHING);
      SDL_SetVideoMode(800, 800, 0, SDL_OPENGL);
  
      glClearColor(1, 0, 0, 0);
  
      glMatrixMode(GL_PROJECTION);
      glOrtho(-1, 1, -1, 1, -1, 1);
  
      /* Shaders */
      vertex = glCreateShader(GL_VERTEX_SHADER);
      assert(vertex != 0);
      fragment = glCreateShader(GL_FRAGMENT_SHADER);
      assert(fragment != 0);
  
      GLint length = strlen(vertex_source);
      glShaderSource(vertex, 1, &amp;vertex_source, &amp;length);
      length = strlen(fragment_source);
      glShaderSource(fragment, 1, &amp;fragment_source, &amp;length);
  
      glCompileShader(vertex);
      glCompileShader(fragment);
  
      program = glCreateProgram();
  
      glAttachShader(program, vertex);
      glAttachShader(program, fragment);
  
      glLinkProgram(program);
  
      sampler_loc = glGetUniformLocation(program, "sampler0");
      vertex_loc = glGetAttribLocation(program, "vertex");
      texcoord_loc = glGetAttribLocation(program, "texcoord");
      colour_loc = glGetAttribLocation(program, "colour");
  
      /* VBO */
      glGenBuffers(1, &amp;vbo);
      glBindBuffer(GL_ARRAY_BUFFER, vbo);
      glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &amp;verts[0], GL_STATIC_DRAW);
      glBindBuffer(GL_ARRAY_BUFFER, 0);
  
      /* Texture */
      texture = SOIL_load_OGL_texture("test.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
      assert(texture != 0);
  }
  
  static void draw()
  {
      glClear(GL_COLOR_BUFFER_BIT);
  
      glUseProgram(program);
  
      glActiveTexture(GL_TEXTURE0);
      glBindTexture(GL_TEXTURE_2D, texture);
      glUniform1i(sampler_loc, 0);
  
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      glScalef(.5, .5, .5);
  
      glBindBuffer(GL_ARRAY_BUFFER, vbo);
  
      glEnableVertexAttribArray(0);
  
      glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, position));
      glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, texcoord));
      glVertexAttribPointer(colour_loc, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), offsetof(Vertex, colour));
  
      glDrawArrays(GL_QUADS, 0, 4);
  
      glDisableVertexAttribArray(0);
  
      glBindBuffer(GL_ARRAY_BUFFER, 0);
  
      glBindTexture(GL_TEXTURE_2D, 0);
      glPopMatrix();
  
      glUseProgram(0);
  }
  
  static void shutdown()
  {
      SDL_Quit();
  }
  
  int main()
  {
      init();
      atexit(shutdown);
  
      while(true)
      {
          static SDL_Event event;
          while(SDL_PollEvent(&amp;event)) 
          {
              switch(event.type) 
              {
                  case SDL_QUIT:
                      exit(0);
                      break;
  
                  default:
                      break;
              }
          }
  
          draw();
  
          SDL_GL_SwapBuffers();
  
          if(glGetError() != GL_NO_ERROR)
          {
              printf("Error\n");
              exit(1);
          }
      }
  
      return 0;
  }
  </code></pre>
  
  <p>The only thing that renders is a plain blue square on top of the glClearColor.</p>
  
  <p>Any help much appreciated.</p>
  
  <p>Thanks for answers, I've attached fixed code for completeness.</p>
  
  <pre><code>#include &lt;stdbool.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;assert.h&gt;
  
  #include &lt;SDL/SDL.h&gt;
  #include &lt;GL/GLee.h&gt;
  #include &lt;SOIL/SOIL.h&gt;
  
  static const char *vertex_source = " \
  uniform mat4 projection; \
  uniform mat4 view_model; \
   \
  attribute vec2 vertex; \
  attribute vec2 texcoord; \
  attribute vec4 colour; \
   \
  varying vec2 _texcoord; \
   \
  void main() \
  { \
      gl_Position = gl_ModelViewProjectionMatrix * vec4(vertex, 0, 1); \
      _texcoord = texcoord; \
      gl_FrontColor = colour; \
  } ";
  
  static const char *fragment_source = " \
  uniform sampler2D sampler0; \
   \
  varying vec2 _texcoord; \
   \
  void main() \
  { \
      gl_FragColor = texture2D(sampler0, _texcoord) + gl_Color; \
  } ";
  
  typedef struct
  {
      GLfloat position[2];
      GLfloat texcoord[2];
      GLubyte colour[4];
  } Vertex;
  
  static Vertex verts[] = {
          {
              .position = { 1, 1 },
              .texcoord = { 1, 1 },
              .colour = { 255, 0, 0, 255 },
          },
          {
              .position = { -1, 1 },
              .texcoord = { 0, 1 },
              .colour = { 0, 255, 0, 255 },
          },
          {
              .position = { -1, -1 },
              .texcoord = { 0, 0 },
              .colour = { 0, 0, 255, 255 },
          },
          {
              .position = { 1, -1 },
              .texcoord = { 1, 0 },
              .colour = { 255, 255, 0, 255 },
          },
      };
  
  static GLuint vertex, fragment, program, vbo, texture;
  static GLint sampler_loc, vertex_loc, texcoord_loc, colour_loc;
  
  static void init()
  {
      SDL_Init(SDL_INIT_EVERYTHING);
      SDL_SetVideoMode(800, 800, 0, SDL_OPENGL);
  
      glClearColor(1, 0, 0, 0);
  
      glMatrixMode(GL_PROJECTION);
      glOrtho(-1, 1, -1, 1, -1, 1);
  
      /* Shaders */
      vertex = glCreateShader(GL_VERTEX_SHADER);
      assert(vertex != 0);
      fragment = glCreateShader(GL_FRAGMENT_SHADER);
      assert(fragment != 0);
  
      GLint length = strlen(vertex_source);
      glShaderSource(vertex, 1, &amp;vertex_source, &amp;length);
      length = strlen(fragment_source);
      glShaderSource(fragment, 1, &amp;fragment_source, &amp;length);
  
      glCompileShader(vertex);
      glCompileShader(fragment);
  
      program = glCreateProgram();
  
      glAttachShader(program, vertex);
      glAttachShader(program, fragment);
  
      glLinkProgram(program);
  
      sampler_loc = glGetUniformLocation(program, "sampler0");
      vertex_loc = glGetAttribLocation(program, "vertex");
      texcoord_loc = glGetAttribLocation(program, "texcoord");
      colour_loc = glGetAttribLocation(program, "colour");
  
      glUseProgram(program);
      glUniform1i(sampler_loc, 0);
      glUseProgram(0);
  
      /* VBO */
      glGenBuffers(1, &amp;vbo);
      glBindBuffer(GL_ARRAY_BUFFER, vbo);
  
      glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &amp;verts[0], GL_STATIC_DRAW);
      glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, position));
      glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, texcoord));
      glVertexAttribPointer(colour_loc, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), offsetof(Vertex, colour));
  
      glBindBuffer(GL_ARRAY_BUFFER, 0);
  
      /* Texture */
      texture = SOIL_load_OGL_texture("test.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
      assert(texture != 0);
  }
  
  static void draw()
  {
      glClear(GL_COLOR_BUFFER_BIT);
  
      glUseProgram(program);
  
      glActiveTexture(GL_TEXTURE0);
      glBindTexture(GL_TEXTURE_2D, texture);
  
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      glScalef(.5, .5, .5);
  
      glEnableVertexAttribArray(vertex_loc);
      glEnableVertexAttribArray(texcoord_loc);
      glEnableVertexAttribArray(colour_loc);
  
      glDrawArrays(GL_QUADS, 0, 4);
  
      glDisableVertexAttribArray(vertex_loc);
      glDisableVertexAttribArray(texcoord_loc);
      glDisableVertexAttribArray(colour_loc);
  
      glBindTexture(GL_TEXTURE_2D, 0);
      glPopMatrix();
  
      glUseProgram(0);
  }
  
  static void shutdown()
  {
      SDL_Quit();
  }
  
  int main()
  {
      init();
      atexit(shutdown);
  
      while(true)
      {
          static SDL_Event event;
          while(SDL_PollEvent(&amp;event)) 
          {
              switch(event.type) 
              {
                  case SDL_QUIT:
                      exit(0);
                      break;
  
                  default:
                      break;
              }
          }
  
          draw();
  
          SDL_GL_SwapBuffers();
  
          if(glGetError() != GL_NO_ERROR)
          {
              printf("Error\n");
              exit(1);
          }
      }
  
      return 0;
  }
  </code></pre>