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

How to view a renderbuffer of GLuints on the screen?

为了获得在屏幕上绘制的元素的某种索引,我创建了一个帧缓冲区,它将使用 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)

我用 readpixel 读取索引是这样的:

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

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

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

根据下面得到的数据,如何在屏幕上看到绘制索引(unsigned 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,这可能行不通,甚至无法达到您的预期.

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

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

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 纹理并在整个 canvas 上绘制一个四边形。四边形的范围应从 (-1,-1) 到 (1,1),纹理坐标的范围从 (0, 0) 到 (1, 1)。
当然,您可以使用着色器,在片段着色器中使用统一的纹理采样器。您可以从纹理中读取纹素,以您想要的方式写入片段。

答案的扩展

如果性能不重要,那么你可以在CPU上转换缓冲区并在glReadPixels读取帧缓冲区后在canvas上绘制它。
为此,您可以保持代码不变并使用 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);

从现在开始你有两种可能。
您要么创建一个新的帧缓冲区并将纹理附加到它的颜色平面

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

并且您使用 glBlitFramebuffer 如上所述从 debug 帧缓冲区复制到颜色平面。 这应该没有问题,因为缓冲区的内部格式应该相同。

或者在整个视口上绘制一个带纹理的四边形。代码可能看起来像这样(老派):

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();