Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

opengl

shader

fbo

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.

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.

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.

like image 337
mjwach Avatar asked May 04 '15 07:05

mjwach


1 Answers

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.

like image 118
Sergey K. Avatar answered Sep 28 '22 08:09

Sergey K.