如何在屏幕上查看 GLuint 的渲染缓冲区?



为了获得屏幕上绘制的元素的索引,我创建了一个帧缓冲区,它将绘制具有 GL_R32UI 类型纯色的对象。

我创建的帧缓冲区附加了两个渲染缓冲区。一个是颜色,一个是深度。以下是如何使用python创建它的示意图:

my_fbo = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, my_fbo)
rbo = glGenRenderbuffers(2) # GL_DEPTH_COMPONENT16 and GL_COLOR_ATTACHMENT0
glBindRenderbuffer(GL_RENDERBUFFER, rbo[0])
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo[0])
glBindRenderbuffer(GL_RENDERBUFFER, rbo[1])
glRenderbufferStorage(GL_RENDERBUFFER, GL_R32UI, width, height)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[1])
glBindRenderbuffer(GL_RENDERBUFFER, 0)        
glBindFramebuffer(GL_FRAMEBUFFER, 0)

我像这样用读取像素读取索引:

glBindFramebuffer(GL_FRAMEBUFFER, my_fbo)
glReadPixels(x, y, threshold, threshold, GL_RED_INTEGER, GL_UNSIGNED_INT, r_data)
glBindFramebuffer(GL_FRAMEBUFFER, 0)

代码运行完美,我没有问题。

但是为了调试,我想在屏幕上看到索引

使用下面获得的数据,我如何看到在屏幕上绘制索引(无符号 int(的结果?

active_fbo = glGetIntegerv(GL_FRAMEBUFFER_BINDING)
my_indices_fbo = my_fbo
my_rbo_depth = rbo[0]
my_rbo_color = rbo[1]
## how mix my_rbo_color and cur_fbo??? ##
glBindFramebuffer(gl.GL_FRAMEBUFFER, active_fbo)
glBlitFramebuffer

将像素值的矩形从读取帧缓冲区的一个区域传输到绘制帧缓冲区的另一个区域。

glBindFramebuffer( GL_READ_FRAMEBUFFER, my_fbo  );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, active_fbo );
glBlitFramebuffer( 0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST );

请注意,您必须小心,因为如果读取缓冲区包含无符号整数值,并且任何绘制缓冲区不包含无符号整数值,则会发生GL_INVALID_OPERATION错误。由于帧缓冲区颜色附件的内部格式是GL_R32UI,并且绘图缓冲区的内部格式通常类似于GL_RGBA8,这可能不起作用,甚至不会执行您的预期。

但是,您可以创建一个帧缓冲区,并将纹理附加到其颜色平面,并将纹理用作后期通道的输入,在整个画布上绘制一个四边形。

首先,您必须创建大小作为帧缓冲区的纹理:

ColorMap0 = glGenTextures(1);
glBindTexture(GL_TEXTURE_2D, ColorMap0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, width, height, 0, GL_R, GL_UNSIGNED_INT, 0);

您必须将纹理附加到帧缓冲区:

my_fbo = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, my_fbo)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColorMap0, 0);

绘制场景后,必须释放帧缓冲。

glBindFramebuffer(GL_FRAMEBUFFER, 0)

现在,您可以将纹理用作最终通道的输入。 只需绑定纹理,启用 2D 纹理并在整个画布上绘制一个四边形。四边形的范围应为 (-1,-1( 到 (1,1(,纹理坐标的范围为 (0, 0( 到 (1, 1(。
当然,您可以使用着色器,在片段着色器中统一纹理采样器。您可以以所需的方式从纹理中读取纹素,然后写入片段。

答案的扩展

如果性能不重要,则可以在使用glReadPixels读取帧缓冲区后,转换 CPU 上的缓冲区并将其绘制在画布上。
为此,您可以保持代码原样并使用glReadPixels读取帧缓冲区,但您必须将缓冲区转换为适合绘图缓冲区的格式。我建议使用 内部格式GL_RGBA8GL_RGB8
您必须使用转换缓冲区数据创建新纹理。

debugTexturePlane = ...; 
debugTexture = glGenTextures(1);
glBindTexture(GL_TEXTURE_2D, debugTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, debugTexturePlane);

从现在开始,您有2种可能性。
创建新的帧缓冲区并将纹理附加到其颜色平面

debugFbo = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, debugFbo)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, debugTexture, 0);

然后使用如上所述glBlitFramebuffer调试帧缓冲区复制到颜色平面。 这应该不是任何问题,因为缓冲区的内部格式应该相等。

或者,在整个视口上绘制一个带纹理的四边形。代码可能如下所示(老派(:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, debugTexture);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex2f(-1.0,  1.0);
glTexCoord2f(1.0, 1.0); glVertex2f( 1.0,  1.0);
glTexCoord2f(1.0, 0.0); glVertex2f( 1.0, -1.0);
glEnd();

最新更新