使用glReadPixels时是否可以不钳位数据?

时间:2019-04-24 13:16:44

标签: c++ opengl

我正在尝试开发一个代码,在其中使用assimp加载3d模型,使用3d坐标和顶点法线进行处理,然后将纹理检索到CPU。

我尝试使用“ glReadPixels”来检索纹理,但是我的数据被夹在here中描述的[0 1]之间。

我使用的纹理示例:

    glGenTextures(1, &pos3d);
    glBindTexture(GL_TEXTURE_2D, pos3d);
    glViewport(0, 0, width, height);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + gpos3dLayout, GL_TEXTURE_2D, pos3d, 0);
    glBindTexture(GL_TEXTURE_2D, 0);

然后我用这个来检索:

    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, pos3d);
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    std::vector<GLfloat> positions3d(width * height * 4); // 4 because of RGBA * 1 float
    glReadPixels(0, 0, width, height, GL_RGBA, GL_FLOAT, &positions3d[0]);

正如我所说,我的值似乎限制在0到1之间。那么有没有办法禁用这种限制?

1 个答案:

答案 0 :(得分:2)

数据被钳位,因为附加到帧缓冲区颜色平面的纹理的内部格式为GL_RGBA(与GL_RGBA8相同)。此格式是无符号归一化定点格式,并为每个颜色通道提供8位,其中0表示0.0,而所有8位设置(255)表示1.0。
这导致纹理的数据存储中的数据表示受到限制。 glReadPixels从数据存储区读取数据,该数据存储区附加到frambuffer的颜色平面。

在通过glTexImage2D指定二维纹理图像时,将纹理的内部格式更改为浮点格式(例如GL_RGBA16F

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);

从缓冲区中读取像素时,它们可能会被限制在[0.0,1.0]范围内。 这取决于glClampColor的设置。

请参见OpenGL 4.6 API Core Profile Specification - 18.2.8 Final Conversion,第535页

  

读取颜色钳制是通过调用控制的

     

void ClampColor( enum target, enum clamp )

     

,目标设置为CLAMP_READ_COLOR。如果钳位为TRUE,则启用读取色钳位;如果钳位为FALSE,则禁用读取色钳位。 [...]
  对于浮点RGBA颜色,如果类型为FLOATHALF_FLOAT,则在启用读取颜色钳位的情况下,每个分量都钳位到[0,1]。

注意,在OpenGL ES中,颜色在任何情况下都是固定的。


glGetTexImage仅在桌面OpenGL中提供,不会钳制颜色。