在 OpenGL 中,我试图将未缩放的 float 从我的片段着色器输出到 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);
...
但是,当我使用以下片段着色器输出到第二个颜色附件时,没有绘制任何内容。我从 glReadPixels() 取回了用 (clearMagnitude) 清除的颜色
#version 330
in float scale;
uniform sampler1D uPalette;
layout(location=0) out vec4 color;
layout(location=1) out float oScale;
void main(void)
{
color = texture(uPalette,scale);
oScale = scale;
}
另一方面,当我使用以下(显然错误)片段着色器进行输出时,我在 glReadPixels() 中得到一个缩放的 (0-1) 值:
#version 330
in float scale;
uniform sampler1D uPalette;
layout(location=0) out vec4 color;
layout(location=1) out vec4 oScale;
void main(void)
{
color = texture(uPalette,scale);
oScale = vec4(scale,scale,scale,1);
}
我做错了什么?我如何在 GLSL 中输出和读回单个未缩放的 float ?
最佳答案
I output using the following (clearly wrong) fragment shader
那个片段着色器没有任何问题。就像顶点属性一样,片段着色器输出组件计数不必与实际目标图像的组件计数相匹配。如果您的输出图像的组件少于相应的片段着色器变量,那么它将只获取与图像匹配的组件并忽略其余组件。
但是,您没有输出 vec4
只是为了写入单 channel 图像。您的 float
示例应该可以正常工作,因此可能存在驱动程序错误。
至于缩放问题,那是另一回事的错:read color clamping .您必须使用 glClampColor
告诉 OpenGL 不要限制浮点读取。像这样:
glClampColor(GL_CLAMP_READ_COLOR, GL_FIXED_ONLY);
这可以防止在读取具有定点格式的 FBO 附加图像时发生夹紧。
这不是 FBO 状态的一部分;这只是一个上下文值。因此,您只需设置一次即可忘记它。
关于c++ - GL_32F 和 glReadPixels,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42325388/