C++ GL_32F和glread像素

C++ GL_32F和glread像素,c++,opengl,glsl,C++,Opengl,Glsl,在OpenGL中,我试图将未缩放的浮点从片段着色器输出到FBO颜色附件,以便鼠标在值上拾取。但是,我无法让片段着色器代码正确写入值 我添加了一个颜色附件,用于将拾取值存储到我绘制的帧缓冲区,如下所示: // ... Bind FBO .etc. glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, DrawTextureDims.width(), DrawTextureDims.height(), 0, GL_R

在OpenGL中,我试图将未缩放的浮点从片段着色器输出到FBO颜色附件,以便鼠标在值上拾取。但是,我无法让片段着色器代码正确写入值

我添加了一个颜色附件,用于将拾取值存储到我绘制的帧缓冲区,如下所示:

// ... Bind FBO .etc.
glTexImage2D(
    GL_TEXTURE_2D,
    0,
    GL_R32F,
    DrawTextureDims.width(),
    DrawTextureDims.height(),
    0,
    GL_RED,
    GL_FLOAT,
    0);
glFramebufferTexture2D(
    GL_FRAMEBUFFER,
    GL_COLOR_ATTACHMENT2,
    GL_TEXTURE_2D,
    pointsMeshData->magnitudeTexture,
    0);
    // ...
    GLenum drawBufs[2] {
        GL_COLOR_ATTACHMENT0,
        GL_COLOR_ATTACHMENT2
    };
    glDrawBuffers(2,drawBufs);

    GLfloat clearMagnitude[4] { 0,0,0,0 };
    glClearBufferfv(GL_COLOR,1,clearMagnitude);

    // Bind VAO and shader. Setup uniforms and call glDrawElements()
...
glBindFramebuffer(GL_READ_FRAMEBUFFER,drawData->renderFBO.handle());
glReadBuffer(GL_COLOR_ATTACHMENT2);
glBindBuffer(GL_PIXEL_PACK_BUFFER,0);

*magnitude = 0.f;
glReadPixels(x,y,1,1,GL_RED,GL_FLOAT,magnitude);
...
并在绘制之前设置绘制缓冲区,如下所示:

// ... Bind FBO .etc.
glTexImage2D(
    GL_TEXTURE_2D,
    0,
    GL_R32F,
    DrawTextureDims.width(),
    DrawTextureDims.height(),
    0,
    GL_RED,
    GL_FLOAT,
    0);
glFramebufferTexture2D(
    GL_FRAMEBUFFER,
    GL_COLOR_ATTACHMENT2,
    GL_TEXTURE_2D,
    pointsMeshData->magnitudeTexture,
    0);
    // ...
    GLenum drawBufs[2] {
        GL_COLOR_ATTACHMENT0,
        GL_COLOR_ATTACHMENT2
    };
    glDrawBuffers(2,drawBufs);

    GLfloat clearMagnitude[4] { 0,0,0,0 };
    glClearBufferfv(GL_COLOR,1,clearMagnitude);

    // Bind VAO and shader. Setup uniforms and call glDrawElements()
...
glBindFramebuffer(GL_READ_FRAMEBUFFER,drawData->renderFBO.handle());
glReadBuffer(GL_COLOR_ATTACHMENT2);
glBindBuffer(GL_PIXEL_PACK_BUFFER,0);

*magnitude = 0.f;
glReadPixels(x,y,1,1,GL_RED,GL_FLOAT,magnitude);
...
最后,请阅读以下内容:

// ... Bind FBO .etc.
glTexImage2D(
    GL_TEXTURE_2D,
    0,
    GL_R32F,
    DrawTextureDims.width(),
    DrawTextureDims.height(),
    0,
    GL_RED,
    GL_FLOAT,
    0);
glFramebufferTexture2D(
    GL_FRAMEBUFFER,
    GL_COLOR_ATTACHMENT2,
    GL_TEXTURE_2D,
    pointsMeshData->magnitudeTexture,
    0);
    // ...
    GLenum drawBufs[2] {
        GL_COLOR_ATTACHMENT0,
        GL_COLOR_ATTACHMENT2
    };
    glDrawBuffers(2,drawBufs);

    GLfloat clearMagnitude[4] { 0,0,0,0 };
    glClearBufferfv(GL_COLOR,1,clearMagnitude);

    // Bind VAO and shader. Setup uniforms and call glDrawElements()
...
glBindFramebuffer(GL_READ_FRAMEBUFFER,drawData->renderFBO.handle());
glReadBuffer(GL_COLOR_ATTACHMENT2);
glBindBuffer(GL_PIXEL_PACK_BUFFER,0);

*magnitude = 0.f;
glReadPixels(x,y,1,1,GL_RED,GL_FLOAT,magnitude);
...
但是,当我使用以下片段着色器输出到第二个颜色附件时,不会绘制任何内容。我从glReadPixels()中获取我清除的颜色(clearMagnitude)

另一方面,当我使用以下(明显错误的)片段着色器输出时,我会在glReadPixels()中得到一个缩放(0-1)值:

我做错了什么?如何在GLSL中输出并读回单个无标度浮点

我使用以下(明显错误的)片段着色器输出

片段着色器没有任何问题。与顶点属性一样,片段着色器输出组件计数不必与实际目标图像的组件计数匹配。如果输出图像的组件少于相应的fragment shader变量,则它将只获取与图像匹配的组件,而忽略其余的组件

但是,您不必输出
vec4
,只需写入单通道图像即可。您的
float
示例应该运行良好,因此可能存在驱动程序错误

至于缩放问题,这是另一件事的错误:。必须使用
glClampColor
告诉OpenGL不要钳制浮点读取。像这样:

glClampColor(GL_CLAMP_READ_COLOR, GL_FIXED_ONLY);
这样可以防止在读取具有定点格式的FBO附着图像时发生夹持

这不是FBO状态的一部分;它只是一个上下文值。因此,您只需设置一次就可以忘记它。

oScale=vec4(scale,scale,scale,/1/);真正地