title: Drawing pixels in OpenGL
body: <p>I'm taking a Computer Graphics course at my university. I need to implement basic line drawing algorithms in modern OpenGL(3.3+) to draw primitives on the screen. Here's the function for Bresenham's Line Drawing Algorithm that I want to implement - 
  </p>
  
  <pre class="lang-cpp prettyprint-override"><code>void bresenham(GLint xStart, GLint yStart, GLint xEnd, GLint yEnd) {
      if (!(xStart &lt; xEnd)) {
      swap(xStart, xEnd);
      swap(yStart, yEnd); 
      }
  
      GLint dx = xEnd - xStart;
      GLint dy = yEnd - yStart;
      GLint p = 2 * dy - dx;
  
      GLint x = xStart;
      GLint y = yStart;
      setPixel(x,y);
  
      while (x &lt; xEnd) {
          x += 1;
          if (p &lt; 0)
              p += (2 * dy);
          else {
              p += (2 * (dy - dx));
              y += 1;
          setPixel(x,y);
          }
      }
  }
  </code></pre>
  
  <p>I'm clueless on how to realise the <code>setPixel()</code> function. Most answers I found here and elsewhere use older OpenGL functions - </p>
  
  <pre class="lang-cpp prettyprint-override"><code>void setPixel(int x, int y)
  {
      glColor3f(0.0, 0.0, 0.0); //Set pixel to black  
      glBegin(GL_POINTS);
      glVertex2i(x, y); //Set pixel coordinates 
      glEnd();
      glFlush(); //Render pixel
  }
  </code></pre>
  
  <p>What is the equivalent way to do this in OpenGl 3.3+?
  Assuming I can add the "pixels" to an <code>std::vector</code> array, how do I initialise the vertex buffer array to store this data? </p>
  
  <p>Another problem I ran into while trying to plot a point using <code>GL_POINTS</code> is that due to clipping during conversion to normalised device coordinates, points beyond the range [-1,1] in either direction do not show on the window. </p>
  
  <p>For example, only the first three points show up on the window screen. See the <code>initialize()</code> function  - </p>
  
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  
  #include &lt;GL/glew.h&gt;
  #include &lt;GLFW/glfw3.h&gt;
  #include &lt;cstdlib&gt;
  #include &lt;vector&gt;
  #include &lt;iostream&gt;
  #include &lt;fstream&gt;
  
  // Read a shader source from a file
  // store the shader source in a std::vector&lt;char&gt;
  void read_shader_src(const char* fname, std::vector&lt;char&gt; &amp;buffer);
  
  // Compile a shader
  GLuint load_and_compile_shader(const char *fname, GLenum shaderType);
  
  // Create a program from two shaders
  GLuint create_program(const char *path_vert_shader, const char *path_frag_shader);
  
  // Render scene
  void display(GLuint &amp;vao, GLFWwindow* window);
  
  // Initialize the data to be rendered
  void initialize(GLuint &amp;vao);
  
  
  //GLFW Callbacks
  static void error_callback(int error, const char* description) {
      fprintf(stderr, "Error: %s\n", description);
  }
  
  static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
      if(key == GLFW_KEY_ESCAPE &amp;&amp; action == GLFW_PRESS) {
          glfwSetWindowShouldClose(window, GL_TRUE);
      }
  }
  
  int main() {
      glfwSetErrorCallback(error_callback);
      //Initialize GLFW
      if (!glfwInit()) {
          fprintf(stderr, "Failed to initialize GLFW.\n");
          return -1;
      }
  
      //Set GLFW window settings and create window
      glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
      glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
      glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
      glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
      GLFWwindow* window = glfwCreateWindow(500, 500, "My window", NULL, NULL);
      if(!window) {
          fprintf(stderr, "Window or context creation failed.\n");
          return -1;
      }
  
      glfwSetKeyCallback(window, key_callback);
      glfwMakeContextCurrent(window);
  
      //Initialize GLEW
      glewExperimental = GL_TRUE;
      if(glewInit() != GLEW_OK) {
          fprintf(stderr, "Failed to initialize glew");
          glfwTerminate();
          return -1;
      }
      //Create a vertex array object
      GLuint vao;
  
      //Initialize the data to be rendered
      initialize(vao);
  
      while (!glfwWindowShouldClose(window)) {
          display(vao, window);
          glfwPollEvents();
      }
      glfwTerminate();
      return 0;
  }
  
  //Render scene
  void display(GLuint &amp;vao, GLFWwindow* window) {
      //Red background
      glClearColor(1.0f, 0.0f, 0.0f, 0.0f); 
      glClear(GL_COLOR_BUFFER_BIT);
  
      glBindVertexArray(vao);
      glDrawArrays(GL_POINTS, 0, 12);
      // Swap front and back buffers
      glfwSwapBuffers(window);
  }
  
  void initialize(GLuint &amp;vao) {
      glEnable(GL_PROGRAM_POINT_SIZE);
      // Use a Vertex Array Object
      glGenVertexArrays(1, &amp;vao);
      glBindVertexArray(vao);
  
      //Store verex positions in an array
      GLfloat vertices[24] = {
          0.0, 0.0, // Only these
          0.5, 0.5, //three points show up
          1.0, 1.0, //on the window screen
  
          4.0, 4.0,
          5.0, 5.0,
          6.0, 6.0,
  
          7.0, 7.0,
          8.0, 8.0,
          9.0, 9.0,
  
          10.0, 10.0,
          11.0, 11.0,
          12.0, 12.0,
      };
  
      //Create a vertex buffer object to store the vertex data
      GLuint vbo;
      //Generates 1 buffer object name and stores it in vbo
      glGenBuffers(1, &amp;vbo);
      //Bind the buffer object to the buffer binding target
      glBindBuffer(GL_ARRAY_BUFFER, vbo);
      //Creates and initializes the buffer object's data store(with data from vertices)
      glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  
      GLuint shaderProgram = create_program("/Users/.../vert.shader", "/Users/.../frag.shader"); //path to shader files
  
      // Get the location of the attributes that enters in the vertex shader
      GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
  
      // Specify how the data for position can be accessed
      glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
  
      //Enable the attribute
      glEnableVertexAttribArray(posAttrib);
  }
  
  // Read a shader source from a file
  // store the shader source in a std::vector&lt;char&gt;
  void read_shader_src(const char *fname, std::vector&lt;char&gt; &amp;buffer) {
      std::ifstream in;
      in.open(fname, std::ios::binary);
  
      if(in.is_open()) {
          // Get the number of bytes stored in this file
          in.seekg(0, std::ios::end);
          size_t length = (size_t)in.tellg();
  
          // Go to start of the file
          in.seekg(0, std::ios::beg);
  
          // Read the content of the file in a buffer
          buffer.resize(length + 1);
          in.read(&amp;buffer[0], length);
          in.close();
          // Add a valid C - string end
          buffer[length] = '\0';
      }
      else {
          std::cerr &lt;&lt; "Unable to open " &lt;&lt; fname &lt;&lt; " I'm out!" &lt;&lt; std::endl;
          exit(-1);
      }
  }
  
  //Compile a shader
  GLuint load_and_compile_shader(const char* fname, GLenum shaderType) {
      //Load a shader from an external file
      std::vector&lt;char&gt; buffer;
      read_shader_src(fname, buffer);
      const char *src = &amp;buffer[0];
  
      //Create and compile the shader
      GLuint shader = glCreateShader(shaderType);
      glShaderSource(shader, 1, &amp;src, NULL);
      glCompileShader(shader);
  
      GLint shader_compiled;
      glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;shader_compiled);
      if(!shader_compiled) {
          GLchar message[1024];
          glGetShaderInfoLog(shader, 1024, NULL, message);
          std::cerr &lt;&lt; "Shader compilation failed.";
          std::cerr &lt;&lt; "Log: " &lt;&lt; &amp;message &lt;&lt; std::endl;
          glfwTerminate();
          exit(-1);
      }
      return shader;
  }
  
  // Create a program from two shaders
  GLuint create_program(const char *path_vert_shader, const char *path_frag_shader) {
      // Load and compile the vertex and fragment shaders
      GLuint vertexShader = load_and_compile_shader(path_vert_shader, GL_VERTEX_SHADER);
      GLuint fragmentShader = load_and_compile_shader(path_frag_shader, GL_FRAGMENT_SHADER);
  
      // Attach the above shader to a program
      GLuint shaderProgram = glCreateProgram();
      glAttachShader(shaderProgram, vertexShader);
      glAttachShader(shaderProgram, fragmentShader);
  
      // Flag the shaders for deletion
      glDeleteShader(vertexShader);
      glDeleteShader(fragmentShader);
  
      // Link and use the program
      glLinkProgram(shaderProgram);
      glUseProgram(shaderProgram);
  
      return shaderProgram;
  }
  </code></pre>
  
  <p>What modifications do I make so I can plot the rest of the points?</p>
  
  <p>Vertex Shader - </p>
  
  <pre class="lang-cpp prettyprint-override"><code>#version 150 core
  
  in vec4 position;
  
  void main() {
      gl_Position = position;
      gl_PointSize = 10.0;
  }
  </code></pre>
  
  <p>Fragment Shader - </p>
  
  <pre class="lang-cpp prettyprint-override"><code>#version 150 core
  
  out vec4 out_color;
  
  void main() {
      out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
  </code></pre>