title: Calculate histogram in OPENGL
body: <p>I try to calculate histogram of a image, using OPENGL. I have read some post about that but I still get error. My histogram buffer always return zeros.
  Some post which I have read:</p>
  
  <p><a href="https://github.com/maknoll/GPU/blob/master/exercise06/Histogram" rel="nofollow noreferrer">Maknoll Histogram</a></p>
  
  <p><a href="https://stackoverflow.com/questions/37539335/luminance-histogram-calculation-in-gpu-android-opengl-es-3-0">Luminance histogram calculation in GPU-android opengl es 3.0</a></p>
  
  <p>My code:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;iostream&gt;
  #include &lt;vector&gt;
  
  // Include GLEW
  #include &lt;GL/glew.h&gt;
  
  // Include GLFW
  #include &lt;GLFW/glfw3.h&gt;
  GLFWwindow* window;
  
  // Include GLM
  #include &lt;glm/glm.hpp&gt;
  using namespace glm;
  #include &lt;SOIL.h&gt;
  
  // Shader sources
  const GLchar* vertexSource = "\n"
  "#version 330 core\n"
  "attribute vec3 inPosition;\n"
  "void main()\n"
  "{\n"
  "    float x = inPosition.x;\n"
  "\n"
  "    gl_Position = vec4(\n"
  "        -1.0 + ((x) * 0.0078125),\n"
  "        -1,\n"
  "        0.0,\n"
  "        1.0\n"
  "    );\n"
  "}\n";
  
  const GLchar* fragmentSource = "\n"
  "#version 330 core\n"
  "out vec4 outputColor;\n"
  "void main()\n"
  "{\n"
  "    outputColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
  "}\n";
  
  void CheckStatus(GLuint obj)
  {
      GLint status = GL_FALSE, len = 10;
      if( glIsShader(obj) )   glGetShaderiv( obj, GL_COMPILE_STATUS, &amp;status );
      if( glIsProgram(obj) )  glGetProgramiv( obj, GL_LINK_STATUS, &amp;status );
      if( status == GL_TRUE ) return;
      if( glIsShader(obj) )   glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &amp;len );
      if( glIsProgram(obj) )  glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &amp;len );
      std::vector&lt; char &gt; log( len, 'X' );
      if( glIsShader(obj) )   glGetShaderInfoLog( obj, len, NULL, &amp;log[0] );
      if( glIsProgram(obj) )  glGetProgramInfoLog( obj, len, NULL, &amp;log[0] );
      std::cerr &lt;&lt; &amp;log[0] &lt;&lt; std::endl;
      exit( -1 );
  }
  
  GLfloat buffer[256];
  GLuint hist[256];
  float _image[512*512*3];
  
  int main()
  {
      // Initialise GLFW
      if( !glfwInit() )
      {
          fprintf( stderr, "Failed to initialize GLFW\n" );
          getchar();
          return -1;
      }
  
      glfwWindowHint(GLFW_SAMPLES, 4);
      glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
      glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
      glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
      glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  
      int width, height;
      unsigned char* image = SOIL_load_image("sample_gray.bmp", &amp;width, &amp;height, 0, SOIL_LOAD_RGB);
      unsigned char image_gray[width * height];
      printf("%d\t%d\n", width, height);
  
      for (int i = 0; i &lt; width * height; ++i)
      {
          image_gray[i] = image[i * 3];
          _image[i * 3] = image[i * 3];
          _image[i * 3 + 1] = image[i * 3 + 1];
          _image[i * 3 + 2] = image[i * 3 + 2];
      }
  
      for (int i = 0; i &lt; width * height; ++i)
      {
          hist[image_gray[i]]++;
      }
  
      // Open a window and create its OpenGL context
      window = glfwCreateWindow(width, height, "Basic", NULL, NULL);
      if( window == NULL ){
          fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
          getchar();
          glfwTerminate();
          return -1;
      }
      glfwMakeContextCurrent(window);
  
      // Initialize GLEW
      glewExperimental = true; // Needed for core profile
      if (glewInit() != GLEW_OK) {
          fprintf(stderr, "Failed to initialize GLEW\n");
          getchar();
          glfwTerminate();
          return -1;
      }
  
      // Ensure we can capture the escape key being pressed below
      glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
  
      // Dark blue background
      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  
      GLuint vbo;
      glGenBuffers(1, &amp;vbo);
      glBindBuffer(GL_ARRAY_BUFFER, vbo);
  
      GLuint num_input_data = width * height;
  
      /* Upload data */
      glBufferData(GL_ARRAY_BUFFER, num_input_data * sizeof(float) * 3, _image, GL_STATIC_DRAW);
  
      GLuint vertexShader, fragmentShader, shaderProgram;
      // Create and compile the vertex shader
      vertexShader = glCreateShader(GL_VERTEX_SHADER);
      glShaderSource(vertexShader, 1, &amp;vertexSource, NULL);
      glCompileShader(vertexShader);
      CheckStatus(vertexShader);
      // Create and compile the fragment shader
      fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
      glShaderSource(fragmentShader, 1, &amp;fragmentSource, NULL);
      glCompileShader(fragmentShader);
      CheckStatus(fragmentShader);
      // Link the vertex and fragment shader into a shader program
      shaderProgram = glCreateProgram();
      glAttachShader(shaderProgram, vertexShader);
      glAttachShader(shaderProgram, fragmentShader);
      glBindFragDataLocation(shaderProgram, 0, "outputColor");
      glLinkProgram(shaderProgram);
  
  
      CheckStatus(shaderProgram);
  
      glUseProgram(shaderProgram);
  
  
      // Specify the layout of the vertex data
      GLint posAttrib = glGetAttribLocation(shaderProgram, "inPosition");
      glEnableVertexAttribArray(posAttrib);
      glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
  
      GLuint tex;
      GLuint fbo;
      glGenTextures(1, &amp;tex);
      glBindFramebuffer(GL_FRAMEBUFFER, fbo);
  
      glGenFramebuffers(1, &amp;fbo);
      glActiveTexture(GL_TEXTURE0);
      // glBindTexture(GL_TEXTURE_2D, tex);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 256, 1);
      // glBindTexture(GL_TEXTURE_2D, 0);
  
      glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0);
  
      /* Clear buffer */
      glClearColor(1.0, 0.0, 0.0, 1.0);
      glClear(GL_COLOR_BUFFER_BIT);
  
      glBlendEquation(GL_FUNC_ADD);
      glBlendFunc(GL_ONE, GL_ONE);
      glEnable(GL_BLEND);
  
      /* Init viewport */
      glViewport(0, 0, 256, 1);
      glUseProgram(shaderProgram);
      /* Draw */
      glDrawArrays(GL_POINTS, 0, num_input_data);
  
  
      glReadPixels(0, 0, 256, 1, GL_RED, GL_FLOAT, buffer);
  
      for (int i = 0; i &lt; 256; ++i)
      {
          printf("%d\t%f\t%d\n", i, buffer[i], hist[i]);
      }
  
  }
  </code></pre>
  
  <p>Could anybody help me,thanks in advance.</p>
  
  <p>I have updated my code, it's working now :D</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;iostream&gt;
  #include &lt;vector&gt;
  // Include GLEW
  #include &lt;GL/glew.h&gt;
  
  // Include GLFW
  #include &lt;GLFW/glfw3.h&gt;
  GLFWwindow* window;
  
  // Include GLM
  #include &lt;glm/glm.hpp&gt;
  using namespace glm;
  #include &lt;SOIL.h&gt;
  
  // Shader sources
  const GLchar* vertexSource = "\n"
  "#version 330 core\n"
  "in vec3 inPosition;\n"
  "void main()\n"
  "{\n"
  "    float x = inPosition.x;\n"
  "\n"
  "    gl_Position = vec4(\n"
  "        -1.0 + ((x + 1) * 0.0078125),\n"
  "        0.0,\n"
  "        0.0,\n"
  "        1.0\n"
  "    );\n"
  "}\n";
  
  const GLchar* fragmentSource = "\n"
  "#version 330 core\n"
  "out vec4 outputColor;\n"
  "void main()\n"
  "{\n"
  "    outputColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
  "}\n";
  
  void CheckStatus(GLuint obj)
  {
      GLint status = GL_FALSE, len = 10;
      if( glIsShader(obj) )   glGetShaderiv( obj, GL_COMPILE_STATUS, &amp;status );
      if( glIsProgram(obj) )  glGetProgramiv( obj, GL_LINK_STATUS, &amp;status );
      if( status == GL_TRUE ) return;
      if( glIsShader(obj) )   glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &amp;len );
      if( glIsProgram(obj) )  glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &amp;len );
      std::vector&lt; char &gt; log( len, 'X' );
      if( glIsShader(obj) )   glGetShaderInfoLog( obj, len, NULL, &amp;log[0] );
      if( glIsProgram(obj) )  glGetProgramInfoLog( obj, len, NULL, &amp;log[0] );
      std::cerr &lt;&lt; &amp;log[0] &lt;&lt; std::endl;
      exit( -1 );
  }
  
  void _check_gl_error(int line) 
  {
      GLenum err (glGetError());
  
      while(err!=GL_NO_ERROR) 
      {
          std::string error;
  
          switch(err) 
          {
              case GL_INVALID_OPERATION:      error="INVALID_OPERATION";      break;
              case GL_INVALID_ENUM:           error="INVALID_ENUM";           break;
              case GL_INVALID_VALUE:          error="INVALID_VALUE";          break;
              case GL_OUT_OF_MEMORY:          error="OUT_OF_MEMORY";          break;
              case GL_INVALID_FRAMEBUFFER_OPERATION:  error="INVALID_FRAMEBUFFER_OPERATION";  break;
          }
  
          std::cerr &lt;&lt; "GL_" &lt;&lt; error.c_str() &lt;&lt;":"&lt;&lt;line&lt;&lt;std::endl;
          err=glGetError();
      }
  }
  
  GLfloat buffer[256];
  GLuint hist[256];
  float _image[512*512*3];
  
  int main()
  {
      // Initialise GLFW
      if( !glfwInit() )
      {
          fprintf( stderr, "Failed to initialize GLFW\n" );
          getchar();
          return -1;
      }
  
      glfwWindowHint(GLFW_SAMPLES, 4);
      glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
      glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
      glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
      glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  
      int width, height;
      unsigned char* image = SOIL_load_image("sample_gray.bmp", &amp;width, &amp;height, 0, SOIL_LOAD_RGB);
      unsigned char* image_gray = new unsigned char[width * height];
  
      printf("%d\t%d\n", width, height);
  
  
      for (int i = 0; i &lt; width * height; ++i)
      {
          image_gray[i] = image[i * 3];
          _image[i * 3] = image[i * 3];
          _image[i * 3 + 1] = image[i * 3 + 1];
          _image[i * 3 + 2] = image[i * 3 + 2];
      }
  
      for (int i = 0; i &lt; width * height; ++i)
      {
          hist[image_gray[i]]++;
      }
  
      // Open a window and create its OpenGL context
      window = glfwCreateWindow(width, height, "Basic", NULL, NULL);
      if( window == NULL ){
          fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
          getchar();
          glfwTerminate();
          return -1;
      }
      glfwMakeContextCurrent(window);
  
      // Initialize GLEW
      glewExperimental = true; // Needed for core profile
      if (glewInit() != GLEW_OK) {
          fprintf(stderr, "Failed to initialize GLEW\n");
          getchar();
          glfwTerminate();
          return -1;
      }
      _check_gl_error(__LINE__);
      // Ensure we can capture the escape key being pressed below
      glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
  
      // Dark blue background
      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  
  
      GLuint vao;
      glGenVertexArrays(1, &amp;vao);
      glBindVertexArray(vao);
  
      GLuint vbo;
      glGenBuffers(1, &amp;vbo);
      glBindBuffer(GL_ARRAY_BUFFER, vbo);
  
      GLuint num_input_data = width * height;
  
      /* Upload data */
      glBufferData(GL_ARRAY_BUFFER, num_input_data * sizeof(float) * 3, _image, GL_STATIC_DRAW);
  
      GLuint vertexShader, fragmentShader, shaderProgram;
      // Create and compile the vertex shader
      vertexShader = glCreateShader(GL_VERTEX_SHADER);
      glShaderSource(vertexShader, 1, &amp;vertexSource, NULL);
      glCompileShader(vertexShader);
      CheckStatus(vertexShader);
      // Create and compile the fragment shader
      fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
      glShaderSource(fragmentShader, 1, &amp;fragmentSource, NULL);
      glCompileShader(fragmentShader);
      CheckStatus(fragmentShader);
      // Link the vertex and fragment shader into a shader program
      shaderProgram = glCreateProgram();
      glAttachShader(shaderProgram, vertexShader);
      glAttachShader(shaderProgram, fragmentShader);
      glBindFragDataLocation(shaderProgram, 0, "outputColor");
      glLinkProgram(shaderProgram);
  
  
      CheckStatus(shaderProgram);
  
      glUseProgram(shaderProgram);
  
  
      // Specify the layout of the vertex data
      GLint posAttrib = glGetAttribLocation(shaderProgram, "inPosition");
      glEnableVertexAttribArray(posAttrib);
      glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
  
      GLuint tex;
      GLuint fbo;
      glGenFramebuffers(1, &amp;fbo);
      glBindFramebuffer(GL_FRAMEBUFFER, fbo);
  
      glGenTextures(1, &amp;tex);
      glActiveTexture(GL_TEXTURE0);
      glBindTexture(GL_TEXTURE_2D, tex);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 256, 1, 0, GL_RED, GL_FLOAT, NULL);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      // glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 256, 1);
  
      glBindTexture(GL_TEXTURE_2D, 0);
  
      glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0);
  
      glBindFramebuffer(GL_FRAMEBUFFER, 0);
  
      _check_gl_error(__LINE__);
  
      glBindFramebuffer(GL_FRAMEBUFFER, fbo);
      /* Clear buffer */
      glClearColor(0.0, 0.0, 0.0, 1.0);
      glClear(GL_COLOR_BUFFER_BIT);
  
      glBlendEquation(GL_FUNC_ADD);
      glBlendFunc(GL_ONE, GL_ONE);
      glEnable(GL_BLEND);
      _check_gl_error(__LINE__);
  
  
      /* Init viewport */
      glViewport(0, 0, 256, 1);
      glUseProgram(shaderProgram);
      /* Draw */
      glDrawArrays(GL_POINTS, 0, num_input_data);
  
  
      glReadPixels(0, 0, 256, 1, GL_RED, GL_FLOAT, buffer);
      _check_gl_error(__LINE__);
      for (int i = 0; i &lt; 256; ++i)
      {
          printf("%d\t%f\t%d\n", i, buffer[i], hist[i]);
      }
      free(image_gray);
  }
  </code></pre>
  
  <p>Special thank to @Vallentin for your enthusiasm!</p>