在 OpenGL 中,一个着色器程序是否可以在一次绘制调用中同时渲染到 FBO 和默认帧缓冲区?

In OpenGL is it possible for one shader program, in one draw call, to render to both an FBO and the default framebuffer?

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

我知道我可以在两个 glDraw* 调用(一个渲染到 FBO,一个不渲染)中分别完成这两件事,这将使用两个适当的着色器程序。

而且我认为(仍在了解这一点)我可以主要 同时完成它们,方法是将两个 renderbuffers/textures 附加到一个 FBO,一个 glDraw* 调用一个着色器程序,其片段着色器将适当的值写入对应于多个 FBO 附件的多个输出,并最终将 FBO 中的两个图像之一复制到默认帧缓冲区,通过使用它来纹理场景填充四边形或通过调用 glBlitFramebuffer。

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

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

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

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

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

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

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