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

时间:2017-08-13 16:03:46

标签: opengl-3

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

1 个答案:

答案 0 :(得分:1)

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

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

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