title: Framebuffer object with float texture clamps values
body: <p><strong>I have checked this similar question, but the suggestions did not solve my problem: <a href="https://stackoverflow.com/questions/10950743/low-precision-and-clamping-when-writing-to-floating-point-fbo">Low precision and clamping when writing to floating point FBO</a></strong>.</p>
  
  <p>I am rendering a float image using a framebuffer object as render target. However, the values read by glReadPixels are clamped between 0 and 1. If I try to render my image using normalized values in this range, it works, but values outside this range are clamped to 1 or 0. Follows some parts of the code.</p>
  
  <p>Here is how I created the texture that I attached to the FBO:</p>
  
  <pre><code>    glGenTextures(1, &amp;color_tex); 
      glBindTexture(GL_TEXTURE_RECTANGLE_ARB, color_tex);
      glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
          GL_NEAREST);
      glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
          GL_NEAREST);
      glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB, ResX, ResY, 0,
          GL_RGB, GL_FLOAT, NULL);
  </code></pre>
  
  <p>How I read it after painting:</p>
  
  <pre><code>    glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
      glReadPixels(0, 0, ResX, ResY, GL_RGB, GL_FLOAT, data);
  </code></pre>
  
  <p>I have painted a triangle in the image using </p>
  
  <pre><code>    glColor3f(0.5f, 2.0f, -0.5f);
  </code></pre>
  
  <p>And the pixel values appears as <strong>(0.5f, 1.0f, 0.0f)</strong> in the read buffer.</p>
  
  <p>How can I return values out of this range?</p>
  
  <p><strong>Follows a simplified version of my code (I kept the depth buffer because I use it in the original one):</strong></p>
  
  <p><strong><em>Ps. I corrected the code bellow based on the answer. It works now.</em></strong></p>
  
  <pre><code>#include &lt;GL/glew.h&gt;
  #include &lt;GL/glut.h&gt;
  
  #include &lt;iostream&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  
  #define WINDOW_WIDTH                    800
  #define WINDOW_HEIGHT                   600
  
  bool initGL(int argc, char *argv[])
  {
      // initialize GLUT and glexts
      glutInit(&amp;argc, argv);
      glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
      glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
      glutInitWindowPosition(100, 100);
      glutCreateWindow("FBO");
  
      GLenum err = glewInit();
      if (GLEW_OK != err)
      {
          /* Problem: glewInit failed. */
          printf("Error: %s\n", glewGetErrorString(err));
          return 0;
      }
  
      if (!GLEW_EXT_framebuffer_object)
      {
          printf("Error: no extension GL_EXT_framebuffer_object.");
          return 0;
      }
  
      if (!GLEW_ARB_color_buffer_float)
      {
          printf("Error: no extension ARB_color_buffer_float.");
          return 0;
      }
  
      glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
      glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE);
      glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
  
      return 1;
  }
  
  void glErrorCheck()
  {
      int errCode;
      if ((errCode = glGetError()) != GL_NO_ERROR)
      {
          printf("Failure in OpenGL %d", errCode);
          exit(0);
      }
  }
  
  bool renderFBO()
  {
  
      GLenum status;
      GLuint color_tex, depth_rb, fb;
  
      int ResX, ResY;
  
      ResY = 4;
      ResX = 4;
  
      float *data;
  
      //gen renderbuffer
      glGenRenderbuffers(1, &amp;depth_rb);
      glErrorCheck();
      // initialize depth renderbuffer
      glBindRenderbuffer(GL_RENDERBUFFER, depth_rb);
      glErrorCheck();
      glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, ResX,
              ResY);
  
      glErrorCheck();
  
      // make a texture
      glGenTextures(1, &amp;color_tex);
      // initialize texture that will store the framebuffer image (BGRA type)
      glBindTexture(GL_TEXTURE_RECTANGLE_ARB, color_tex);
      glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
              GL_NEAREST);
      glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
              GL_NEAREST);
      glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
      glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
      glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB, ResX, ResY, 0,
              GL_RGB, GL_FLOAT, NULL);
      glErrorCheck();
  
      // gen the framebuffer object
      glGenFramebuffers(1, &amp;fb);
      // bind the framebuffer, fb, so operations will now occur on it
      glBindFramebuffer(GL_FRAMEBUFFER, fb);
  
      // bind this texture to the current framebuffer obj. as color_attachment_0
      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
              GL_TEXTURE_RECTANGLE_ARB, color_tex, 0);
      glErrorCheck();
  
      glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
              GL_RENDERBUFFER, depth_rb);
      glErrorCheck();
  
      //check framebuffer status
      status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
      if (status != GL_FRAMEBUFFER_COMPLETE)
      {
          glBindFramebuffer(GL_FRAMEBUFFER, 0);
          {
              printf("Failure in OpenGL Framebuffer %d", status);
              return 0;
          }
      }
      glErrorCheck();
  
      //render to GL_TEXTURE_2D
      glBindFramebuffer(GL_FRAMEBUFFER, fb);
      glClearColor(0.0, 0.0, 0.0, 1.0);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
      glViewport(0, 0, ResX, ResY);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(0.0, (float) ResX, 0.0, (float) ResY, -1.0, 1.0);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
  
      glBegin(GL_TRIANGLES);
  
      printf("Original color: %f %f %f\n", 0.5f, 2.0f, -0.5f);
  
      glColor3f(0.5f, 2.0f, -0.5f);
  
      glVertex3f(0.0f, 0.0f, 0.0f);
      glVertex3f((float) ResX, 0.0f, 0.0f);
      glVertex3f((float) ResX, (float) ResY, 0.0f);
  
      glEnd();
  
      // read framebuffer
      glReadBuffer(GL_COLOR_ATTACHMENT0);
      glErrorCheck();
  
      // allocate memory for texture data
      data = new float[ResX * ResY * 3];
      if (data == NULL)
      {
          printf("Out of memory\n");
          return false;
      }
  
      //glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
      glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
  
      glReadPixels(0, 0, ResX, ResY, GL_RGB, GL_FLOAT, data);
      glErrorCheck();
  
      //print the last pixel of the buffer
      int i = ResX * ResY - 1;
      printf("Buffer color: %f %f %f\n", data[i], data[i + 1], data[i + 2]);
  
      // Re-enable rendering to the window
      glBindFramebuffer(GL_FRAMEBUFFER, 0);
      glErrorCheck();
  
      //deallocate data
      delete[] data;
  
      //delete buffers
      glDeleteTextures(1, &amp;color_tex);
      glDeleteRenderbuffers(1, &amp;depth_rb);
      glDeleteFramebuffers(1, &amp;fb);
      glErrorCheck();
  
      return true;
  }
  
  int main(int argc, char **argv)
  {
  
      if (!initGL(argc, argv))
      {
          printf("Failure during GLUT/GLEXT initialization.");
          return 0;
      }
  
      if (!renderFBO())
          printf("Fail!\n");
  
      printf("End!\n");
      return 0;
  
  }
  </code></pre>