GL Shader 1.30 and fragment outputs

I’ve been looking at glslang 1.3, and I’ve got a question about how fragment outputs work.

So, much like attributes, you’re supposed to bind each fragment output variable to a number. As I understand it, this number is supposed to match up with the binding index to an FBO.

So how does it work when drawing to the default framebuffer? Do we have to have two versions of the linked program, one for FBO rendering and one for the default framebuffer?

It doesn’t bind to a color attachment. It binds to a draw buffer, which you set with glDrawBuffer(s). By default this is GL_BACK for the window, and GL_COLOR_ATTACHMENT0 for an FBO. But you can set the draw buffer array to any valid enums you want.

So, let me make sure I understand this.

On the program side, you have a set of fragment output strings, that represent variables that the fragment shader writes to. And on the framebuffer side, you either have the default framebuffer bindings or the FBO color attachment bindings. These are GL enumerators.

To connect them, you have two linkages. First, the program must bind numbers to the output strings. These numbers can only range from 0 to MAX_BUFFERS - 1. Then, you use this glDrawBuffers call to connect those numbers to the GL enumerations. The program bindings are stored in the program object, and the draw buffer bindings are stored in the FBO.

Is all that correct?

Correct.

You can think of the draw buffer array as an indirection table, routing outputs to buffers. The draw buffer state is per-FBO state. So you can set up program outputs and reuse that program with multiple FBOs (as long as the number and type of bound attachments match. If one FBO has float attachments and one has int attachments, the results will be undefined-- you need two different shaders in this case.)

This is all per ARB_draw_buffers, circa OpenGL 1.5. The only new part is binding an arbitrary varying name to a fragment output, per EXT_gpu_shader4. The reason for this is to abstract away the type information-- you can output a float, or int, or uint, without having to add gl_FragColor, gl_FragColorI, gl_FragColorUI, etc to the shading language.