title: Cannot draw a triangle in OpenGL
body: <p>I have recently started to learn OpenGL and have written a little bit of code to draw a simple white triangle in an SDL window. I have read and reread my code, and I have checked it against what was proposed in several opengl tutorials, but I can't make it work. I know that opengl is bound to SDL correctly because I can change the window background color with glClearColor, but I cannot display that darn triangle. </p>
  
  <p>I would happily give out more information but to be honest I don't know any more precisely where the problem comes from, so here's the code I wrote :</p>
  
  <pre><code>int init()
  {
      if(SDL_Init(SDL_INIT_VIDEO) &lt; 0)
      {
          fprintf(stderr, "SDL error : %s\n", SDL_GetError());
          SDL_Quit();
          return -1;
      }
  
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
  
      SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
      SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  
      gWindow = SDL_CreateWindow("Test OpenGL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINWIDTH, WINHEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
      if (gWindow == NULL)
      {
          fprintf(stderr, "Failed to create window. SDL error : %s\n", SDL_GetError());
          SDL_Quit();
          return -1;
      }
  
      gGLContext = SDL_GL_CreateContext(gWindow);
      if (gGLContext == 0)
      {
          fprintf(stderr, "Failed to create OpenGL context. SDL error : %s\n", SDL_GetError());
          SDL_DestroyWindow(gWindow);
          SDL_Quit();
          return -1;
      }
  
      GLenum glewInitResult = glewInit();
      if (glewInitResult != GLEW_OK)
      {
          fprintf(stderr, "Failed to initialize glew. Glew error : %s\n", glewGetErrorString(glewInitResult));
          SDL_GL_DeleteContext(gGLContext);
          SDL_DestroyWindow(gWindow);
          SDL_Quit();
          return -1;
      }
      glEnable(GL_DEPTH_TEST);
  
      return 0;
  }
  
  int loadShader(char *filename, GLint *shader)
  {
      long sz;
      const GLchar *code;
      FILE *fp = fopen(filename, "rb");
      if( !fp ) perror(filename),exit(1);
  
      fseek( fp , 0L , SEEK_END);
      sz = ftell( fp );
      rewind( fp );
  
      code = calloc( 1, sz+1 );
      if( !code ) fclose(fp),fputs("memory alloc fails",stderr),exit(1);
  
      if( 1!=fread( code , sz, 1 , fp) )
        fclose(fp),free(code),fputs("entire read fails",stderr),exit(1);
  
      fclose(fp);
      char *dot = strrchr(filename, '.');
      GLenum type;
      if (dot)
          type = !strcmp(dot, ".vs") ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER;
      *shader = glCreateShader(type);
      glShaderSource(*shader, 1, &amp;code, NULL);
      glCompileShader(*shader);
      GLint status;
      glGetShaderiv(*shader, GL_COMPILE_STATUS, &amp;status);
  
      char buffer[512];
      glGetShaderInfoLog(*shader, sizeof(buffer), NULL, buffer);
      fprintf(stderr, buffer);
      if (status != GL_TRUE)
          return -1;
      return 0;
  }
  
  void printError(char *message)
  {
  #define TEST(ERR) case ERR: fprintf(stderr, "%s : " #ERR "\n", message); break;
      int error;
      if ((error = glGetError()))
          switch (error)
          {
          TEST(GL_INVALID_ENUM)
          TEST(GL_INVALID_VALUE)
          TEST(GL_INVALID_OPERATION)
          TEST(GL_STACK_OVERFLOW)
          TEST(GL_STACK_UNDERFLOW)
          TEST(GL_OUT_OF_MEMORY)
          TEST(GL_INVALID_FRAMEBUFFER_OPERATION)
          TEST(GL_TABLE_TOO_LARGE)
      default:
          fprintf(stderr, "Unknown error\n");
          }
  #undef TEST
  }
  
  int main(int argc, char *argv[])
  {
      if (init() != 0)
          return -1;
  
      float vertices[] = {0.0,  0.5,
                          0.5, -0.5,
                          -.5, -0.5};
      GLuint vbo;
      glGenBuffers(1, &amp;vbo);
      glBindBuffer(GL_ARRAY_BUFFER, vbo);
      glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  
      GLuint vShader;
      GLuint fShader;
      if (loadShader("plain_2d.vs", &amp;vShader) &lt; 0)
          return -1;
      if (loadShader("plain_2d.fs", &amp;fShader) &lt; 0)
          return -1;
      GLint shaderProgram = glCreateProgram();
      glAttachShader(shaderProgram, vShader);
      glAttachShader(shaderProgram, fShader);
      glLinkProgram(shaderProgram);
      glUseProgram(shaderProgram);
  
      GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
      glEnableVertexAttribArray(posAttrib);
      glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
  
      printError("Before entering the loop");
  
      SDL_Event e;
      int quit = 0;
      while (!quit)
      {
          printError("In the loop");
          while (SDL_PollEvent(&amp;e))
          {
              switch (e.type)
              {
              case SDL_QUIT:
                  quit = 1;
              }
          }
  
          glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
          glClear(GL_COLOR_BUFFER_BIT);
  
          glDrawArrays(GL_TRIANGLES, 0, 3);
  
          SDL_GL_SwapWindow(gWindow);
      }
      return 0;
  }
  </code></pre>
  
  <p>printError and loadShader are helper functions that I wrote and am sure work perfectly. Here is the code for the vertex and fragment shaders, which is so basic I don't see how anything wrong could come from there :</p>
  
  <p>VERTEX SHADER</p>
  
  <pre><code>#version 150
  
  in vec2 position;
  
  void main()
  {
      gl_Position = vec4(position, 0.0, 1.0);
  }
  </code></pre>
  
  <p>FRAGMENT SHADER</p>
  
  <pre><code>#version 150
  
  out vec4 outColor;
  
  void main()
  {
      outColor = vec4(1.0, 1.0, 1.0, 1.0);
  }
  </code></pre>
  
  <p>I'm sorry that this is vague, but I did my research and really could not find anything wrong in my code, so I hope that a more experienced person will be able to find the problem.</p>
  
  <p>Thanks in advance!</p>