在OpenGL中,一个绘图调用中的一个着色器程序可以渲染到FBO和默认帧缓冲区吗?

时间:2020-12-20 19:36:52

I would like to draw a scene to the default framebuffer, while also drawing some auxiliary data related to some of my drawn models to an offscreen buffer with the same image dimensions as the default framebuffer.

我想将一个场景绘制到默认的帧缓冲区,同时还将一些与我绘制的模型相关的辅助数据绘制到具有与默认帧缓冲区相同的图像尺寸的屏幕外缓冲区。

I understand I can do these two things separately, in two glDraw* calls (one rendering to an FBO, one not) that will use two appropriate shader programs.

我知道我可以分别做两个这样的事情,两个glDraw *调用(一个渲染到一个FBO,一个不渲染),它将使用两个合适的着色器程序。

And I think (still learning about this) I can do them mostly simultaneously, by attaching two renderbuffers/textures to one FBO, doing one glDraw* call with one shader program whose fragment shader will write appropriate values to multiple outputs corresponding to the multiple FBO attachments, and finally copying one of the two images in the FBO to the default framebuffer, by using it to texture a scene-filling quad or by calling glBlitFramebuffer.

我认为(仍在了解这一点)我可以通过将两个渲染缓冲区/纹理附加到一个FBO来实现它们,使用一个着色器程序执行一次glDraw *调用,其片段着色器将适当的值写入对应于多个FBO的多个输出附件,最后将FBO中两个图像中的一个复制到默认帧缓冲区,使用它来构建场景填充四边形或调用glBlitFramebuffer。

But can I make one glDraw* call, with one shader program, and have my fragment shader write both to the visible framebuffer and some offscreen FBO? I am suspecting not, from what I've seen of the relevant documentation, but I'm not certain.

但是我可以使用一个着色器程序进行一次glDraw *调用,并让我的片段着色器同时写入可见的帧缓冲区和一些屏幕外的FBO吗?从我所看到的相关文档中我不怀疑,但我不确定。

1 个解决方案

#1


No, you cannot draw to different framebuffers at the same time. But you can draw to different draw buffers atteched to a framebuffer. This is possible and called multiple render targets.

不,你不能同时绘制到不同的帧缓冲区。但是你可以绘制到一个帧缓冲区的不同绘制缓冲区。这是可能的,并称为多个渲染目标。

You need to specify draw buffers this way:

您需要以这种方式指定绘制缓冲区:

GLenum DrawBuffers[] =
{
    GL_COLOR_ATTACHMENT0,
    GL_COLOR_ATTACHMENT1,
    GL_COLOR_ATTACHMENT2,
    GL_COLOR_ATTACHMENT3 
};
glDrawBuffers(ARRAY_SIZE_IN_ELEMENTS(DrawBuffers), DrawBuffers);

Then, in a fragment shader, you have to write something like:

然后,在片段着色器中,您必须编写如下内容:

layout (location = 0) out vec3 WorldPosOut;
layout (location = 1) out vec3 DiffuseOut;
layout (location = 2) out vec3 NormalOut;
layout (location = 3) out vec3 TexCoordOut;

uniform sampler2D gColorMap; 

void main()
{
    WorldPosOut = WorldPos0;
    DiffuseOut = texture(gColorMap, TexCoord0).xyz;
    NormalOut = normalize(Normal0);
    TexCoordOut = vec3(TexCoord0, 0.0);
} 

This will output values to all draw buffers at once. Refer to http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html for a complete example.

这将立即将值输出到所有绘制缓冲区。有关完整示例,请参阅http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html。

#1


No, you cannot draw to different framebuffers at the same time. But you can draw to different draw buffers atteched to a framebuffer. This is possible and called multiple render targets.

不,你不能同时绘制到不同的帧缓冲区。但是你可以绘制到一个帧缓冲区的不同绘制缓冲区。这是可能的,并称为多个渲染目标。

You need to specify draw buffers this way:

您需要以这种方式指定绘制缓冲区:

GLenum DrawBuffers[] =
{
    GL_COLOR_ATTACHMENT0,
    GL_COLOR_ATTACHMENT1,
    GL_COLOR_ATTACHMENT2,
    GL_COLOR_ATTACHMENT3 
};
glDrawBuffers(ARRAY_SIZE_IN_ELEMENTS(DrawBuffers), DrawBuffers);

Then, in a fragment shader, you have to write something like:

然后,在片段着色器中,您必须编写如下内容:

layout (location = 0) out vec3 WorldPosOut;
layout (location = 1) out vec3 DiffuseOut;
layout (location = 2) out vec3 NormalOut;
layout (location = 3) out vec3 TexCoordOut;

uniform sampler2D gColorMap; 

void main()
{
    WorldPosOut = WorldPos0;
    DiffuseOut = texture(gColorMap, TexCoord0).xyz;
    NormalOut = normalize(Normal0);
    TexCoordOut = vec3(TexCoord0, 0.0);
} 

This will output values to all draw buffers at once. Refer to http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html for a complete example.

这将立即将值输出到所有绘制缓冲区。有关完整示例,请参阅http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html。