Objeto Framebuffer com valores de grampos de textura flutuante

Eu verifiquei essa questão semelhante, mas as sugestões não resolveram o meu problema:Baixa precisão e fixação ao escrever em ponto flutuante FBO.

Eu estou renderizando uma imagem flutuante usando um objeto framebuffer como destino de renderização. No entanto, os valores lidos por glReadPixels são fixados entre 0 e 1. Se eu tentar renderizar minha imagem usando valores normalizados nesse intervalo, isso funciona, mas valores fora desse intervalo são limitados a 1 ou 0. Segue algumas partes do código.

Aqui está como eu criei a textura que eu anexei ao FBO:

    glGenTextures(1, &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);

Como eu li depois de pintar:

    glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
    glReadPixels(0, 0, ResX, ResY, GL_RGB, GL_FLOAT, data);

Eu pintei um triângulo na imagem usando

    glColor3f(0.5f, 2.0f, -0.5f);

E os valores de pixel aparecem como(0,5f, 1,0f, 0,0f) no buffer de leitura.

Como posso retornar valores fora desse intervalo?

Segue uma versão simplificada do meu código (eu mantive o buffer de profundidade porque eu o uso no original):

Ps. Eu corrigi o código abaixo com base na resposta. Funciona agora.

#include <GL/glew.h>
#include <GL/glut.h>

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

#define WINDOW_WIDTH                    800
#define WINDOW_HEIGHT                   600

bool initGL(int argc, char *argv[])
{
    // initialize GLUT and glexts
    glutInit(&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, &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, &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, &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, &color_tex);
    glDeleteRenderbuffers(1, &depth_rb);
    glDeleteFramebuffers(1, &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;

}

questionAnswers(2)

yourAnswerToTheQuestion