Name ARB_blend_func_extended Name Strings GL_ARB_blend_func_extended Contributors Graham Sellers, AMD Mark Young, AMD Nick Haemel, AMD Pierre Boudier, AMD Mais Alnasser, AMD Jeff Bolz, NVIDIA Pat Brown, NVIDIA Ian Stewart, NVIDIA Mark Kilgard, NVIDIA Contact Graham Sellers, AMD (graham.sellers 'at' amd.com) Notice Copyright (c) 2010-2013 The Khronos Group Inc. Copyright terms at http://www.khronos.org/registry/speccopyright.html Specification Update Policy Khronos-approved extension specifications are updated in response to issues and bugs prioritized by the Khronos OpenGL Working Group. For extensions which have been promoted to a core Specification, fixes will first appear in the latest version of that core Specification, and will eventually be backported to the extension document. This policy is described in more detail at https://www.khronos.org/registry/OpenGL/docs/update_policy.php Status Complete. Approved by the ARB at the 2010/01/22 F2F meeting. Approved by the Khronos Board of Promoters on March 10, 2010. Version Last Modified Date: 05/22/2015 Author Revision: 13 Number ARB Extension #78 Dependencies OpenGL 1.0 is required. The ARB_fragment_shader extension is required. The EXT_gpu_shader4 extension is required. The EXT_blend_func_separate extension interacts with this extension. The ARB_draw_buffers extension trivially affects the definition of this extension. The ARB_draw_buffers_blend extension affects the definition of this extension. This extension is written against the OpenGL 3.2 Specification (Compatibility Profile) Overview Traditional OpenGL includes fixed-function blending that combines source colors with the existing content of a render buffer in a variety of ways. A number of extensions have enhanced this functionality by adding further sources of blending weights and methods to combine them. However, the inputs to the fixed-function blending units are constrained to a source color (as output from fragment shading), destination color (as the current content of the frame buffer) or constants that may be used in their place. This extension adds new blending functions whereby a fragment shader may output two colors, one of which is treated as the source color, and the other used as a blending factor for either source or destination colors. Furthermore, this extension increases orthogonality by allowing the SRC_ALPHA_SATURATE function to be used as the destination weight. IP Status No known IP claims. New Procedures and Functions void BindFragDataLocationIndexed(uint program, uint colorNumber, uint index, const char * name); int GetFragDataIndex(uint program, const char * name); New Tokens Accepted by the and parameters of BlendFunc and BlendFunci, and by the , , and parameters of BlendFuncSeparate and BlendFuncSeparatei: SRC1_COLOR 0x88F9 SRC1_ALPHA ONE_MINUS_SRC1_COLOR 0x88FA ONE_MINUS_SRC1_ALPHA 0x88FB Accepted by the parameter of GetBooleanv, GetIntegerv, GetFloatv and GetDoublev: MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC Additions to Chapter 2 of the OpenGL 3.2 Specification (Compatibility Profile) (OpenGL Operation) None. Additions to Chapter 3 of the OpenGL 3.2 Specification (Compatibility Profile) (Rasterization) Modify the "Shader Outputs" subsection of Section 3.12.2, Shader Execution Modify the text on p.297 beginning "The binding of a user-defined varying out variable to a fragment..." The binding of a user-defined varying out variable to a fragment color number can be specified explicitly. The command void BindFragDataLocationIndexed(uint program, uint colorNumber, uint index, const char * name); specifies that the varying out variable name in should be bound to fragment color when the program is next linked. may be zero or one to specify that the color be used as either the first or second color input to the blend equation, respectively, as described in Section 4.1.8. If was bound previously, its assigned binding is replaced with colorNumber. must be a null-terminated string. The error INVALID_VALUE is generated if is equal or greater than MAX_DRAW_BUFFERS and is zero, or if is equal or greater than MAX_DUAL_SOURCE_DRAW_BUFFERS and is greater than or equal to one. The command void BindFragDataLocation(uint program, uint colorNumber, const char * name) is equivalent to calling BindFragDataLocationIndexed with the same values for , and , and with set to zero. When a program is linked, any varying out variables without a binding specified through BindFragDataLocationIndexed or BindFragDataLocation will automatically be bound to fragment colors and indices by the GL. All such assignments will use color indices of zero. Such bindings can be queried using the commands GetFragDataLocation and GetFragDataIndex. Output binding assignments will cause LinkProgram to fail: * if the number of active outputs is greater than the value of MAX_DRAW_BUFFERS; * if the program has an active output assigned to a location greater than or equal to the value of MAX_DUAL_SOURCE_DRAW_BUFFERS and has an active output assigned an index greater than or equal to one; * if more than one varying out variable is bound to the same number and index; or * if the explicit binding assignments do not leave enough space for the linker to automatically assign a location for a varying out array, which requires multiple contiguous locations. BindFragDataLocationIndexed may be issued before any shader objects are attached to a program object. Hence it is allowed to bind any name (except a name starting with gl_) to a color number and index, including a name that is never used as a varying out variable in any fragment shader object. Assigned bindings for variables that do not exist are ignored. Add to the last paragraph on p.279 The command int GetFragDataIndex(uint program, const char * name); returns the index of the fragment color to which the variable was bound when the program object was last linked. If program has not been successfully linked, the error INVALID_OPERATION is generated. If name is not a varying out variable, or if an error occurs, -1 will be returned. Additions to Chapter 4 of the OpenGL 3.2 Specification (Compatibility Profile) (Per-Fragment Operations and the Framebuffer) Modify the first paragraph of the Blending Functions subsection of Section 4.1.8 Blending (p. 292) as follows: The weighting factors used by the blend equation are determined by the blend functions. There are four possible sources for weighting factors. These are the constant color (Rc, Gc, Bc, Ac) (see BlendColor, p. 211), the first source color (Rs0, Gs0, Bs0, As0), the second source color (Rs1, Gs1, Bs1, As1), and the destination color (the existing content of the draw buffer). Additionally the special constants ZERO and ONE are available as weighting factors. Blend functions are specified ... Modify Table 4.2 (p. 213) as follows RGB Blend Factors Alpha Blend Factors Value (Sr, Sg, Sb) or (Dr, Dg, Db) Sa or Da ----- ---------------------------- ------------------- ZERO (0, 0, 0) 0 ONE (1, 1, 1) 1 SRC_COLOR (Rs0, Gs0, Bs0) As0 ONE_MINUS_SRC_COLOR (1, 1, 1) - (Rs0, Gs0, Bs0) 1 - As0 DST_COLOR (Rd, Gd, Bd) Ad ONE_MINUS_DST_COLOR (1, 1, 1) - (Rd, Gd, Bd) 1 - Ad SRC_ALPHA (As0, As0, As0) As0 ONE_MINUS_SRC_ALPHA (1, 1, 1) - (As0, As0, As0) 1 - As0 DST_ALPHA (Ad, Ad, Ad) Ad ONE_MINUS_DST_ALPHA (1, 1, 1) - (Ad, Ad, Ad) 1 - Ad CONSTANT_COLOR (Rc, Gc, Bc) Ac ONE_MINUS_CONSTANT_COLOR (1, 1, 1) - (Rc, Gc, Bc) 1 - Ac CONSTANT_ALPHA (Ac, Ac, Ac) Ac ONE_MINUS_CONSTANT_ALPHA (1, 1, 1) - (Ac, Ac, Ac) 1 - Ac SRC_ALPHA_SATURATE (f, f, f) 1 (Now allowed for dst) SRC1_COLOR (Rs1, Gs1, Bs1) As1 New ONE_MINUS_SRC1_COLOR (1, 1, 1) - (Rs1, Gs1, Bs1) 1 - As1 New SRC1_ALPHA (As1, As1, As1) As1 New ONE_MINUS_SRC1_ALPHA (1, 1, 1) - (As1, As1, As1) 1 - As1 New Remove Footnote 1 from Table 4.2. Add the following subsections to Section 4.1.8 Blending, at the end of the description of Blend Function (p. 294) Dual Source Blending and Multiple Draw Buffers Blend functions that require the second color input, (SRC1_COLOR, SRC1_ALPHA, ONE_MINUS_SRC1_COLOR, or ONE_MINUS_SRC1_ALPHA) may consume hardware resources that could otherwise be used for rendering to multiple draw buffers. Therefore, the number of draw buffers that can be attached to a frame buffer may be lower when using dual-source blending. The maximum number of draw buffers that may be attached to a single frame buffer when using dual-source blending functions is implementation dependent and can be queried by calling GetIntegerv with the symbolic constant MAX_DUAL_SOURCE_DRAW_BUFFERS. When using dual-source blending, MAX_DUAL_SOURCE_DRAW_BUFFERS should be used in place of MAX_DRAW_BUFFERS to determine the maximum number of draw buffers that may be attached to a single frame buffer. The value of MAX_DUAL_SOURCE_DRAW_BUFFERS must be at least 1. If the value of MAX_DUAL_SOURCE_DRAW_BUFFERS is 1, then dual-source blending and multiple draw buffers cannot be used simultaneously. If either blend function is set to one of the second source factors (SRC1_COLOR, SRC1_ALPHA, ONE_MINUS_SRC1_COLOR, or ONE_MINUS_SRC1_ALPHA) for any draw buffer and any draw buffers equal to or greater than the value of MAX_DUAL_SOURCE_DRAW_BUFFERS have values other than NONE, the error INVALID_OPERATION is generated by Begin, or any procedure that implicitly calls Begin. Generation of Second Color Source for Blending There is no way to generate the second source color using the fixed-function fragment pipeline. Rendering using any of the blend functions that consume the second input color (SRC1_COLOR, ONE_MINUS_SRC1_COLOR, SRC1_ALPHA or ONE_MINUS_SRC1_ALPHA) using fixed function will produce undefined results. To produce input for the second source color, a shader must be used. When using a GLSL fragment shader with dual-source blending functions, the color output varyings are bound to the first and second inputs of a draw buffer using BindFragDataLocationIndexed as described in the "Shader Outputs" subsection of Section 3.12.2. Data written to the first of these outputs becomes the first source color input to the blender (corresponding to SRC_COLOR and SRC_ALPHA). Data written to the second of these outputs generates the second source color input to the blender (corresponding to SRC1_COLOR and SRC1_ALPHA). If the second color input to the blender is not written in the shader, or if no output is bound to the second input of a blender, the result of the blending operation is not defined. Other shading languages may define similar methods for producing the first and second color inputs to blending equations. Additions to Chapter 5 of the OpenGL 3.2 Specification (Compatibility Profile) (Special Functions) None. Additions to Chapter 6 of the OpenGL 3.2 Specification (Compatibility Profile) (State and State Requests) None. Dependencies on ARB_fragment_shader If ARB_fragment_shader is not supported then references to ARB_fragment_shader in section 4.1.8 and elsewhere in this document should be removed. In this case, there is no way to generate the second color input to the blending equation unless a further extension to another shading language is defined and used. Dependencies on ARB_draw_buffers Using dual-source blending functions may consume additional outputs from hardware shading units and therefore can reduce the number of draw buffers that may be attached to a single frame buffer when dual-source blending functions are enabled. In this case, the value of MAX_DUAL_SOURCE_DRAW_BUFFERS may be less than the value of MAX_DRAW_BUFFERS. If ARB_draw_buffers is not supported then the value of MAX_DUAL_SOURCE_DRAW_BUFFERS will be 1. Furthermore, the discussion in the subsection entitled "Dual Source Blending and Multiple Draw Buffers" may be discarded. Dependencies on EXT_blend_func_separate If EXT_blend_func_separate is not supported, remove references to BlendFuncSeparate. Also, remove any references to BLEND_SRC_ALPHA and BLEND_DST_ALPHA, and replace references to BLEND_SRC_RGB and BLEND_DST_RGB with BLEND_SRC and BLEND_DST, respectively. In this case, the new blend functions may only be enabled via the BlendFunc procedure. Dependencies on ARB_draw_buffers_blend If ARB_draw_buffers_blend is not supported, all references to BlendFunci and BlendFuncSeparatei should be removed. In this case, the blend functions for all attached draw buffers will be the same. Interactions with NV_gpu_program5 If NV_gpu_program5 is supported, fragment result bindings "result.color[n].primary" and "result.color[n].secondary" can be used to specify the th color outputs for index 0 and 1, respectively. Additions to the AGL/GLX/WGL Specifications None. GLX Protocol None. Errors The error INVALID_OPERATION is generated by Begin or any procedure that implicitly calls Begin if any draw buffer has a blend function requiring the second color input (SRC1_COLOR, ONE_MINUS_SRC1_COLOR, SRC1_ALPHA or ONE_MINUS_SRC1_ALPHA), and a framebuffer is bound that has more than the value of MAX_DUAL_SOURCE_DRAW_BUFFERS-1 active color attachments. New State Table 6.21 (p. 286) Get Value Type Get Command Initial Value Description Sec Attribute ------------------------ ---- ------------ ------------- ------------------- ----- --------- BLEND_SRC_RGB Z19 GetIntegerv ONE Blending source RGB 4.1.8 color-buffer function BLEND_SRC_ALPHA Z19 GetIntegerv ONE Blending source A 4.1.8 color-buffer function BLEND_DST_RGB Z19 GetIntegerv ZERO Blending dest. RGB 4.1.8 color-buffer function BLEND_DST_ALPHA Z19 GetIntegerv ZERO Blending dest. A 4.1.8 color-buffer function NOTE: The only change is that Z14 and Z15 change to Z19 for the existing blend function state. No new state is actually added to the OpenGL Specification. New Implementation Dependent State Get Value Type Get Command Minimum Value Description Sec. Attribute --------- ---- ----------- ------------- ------------------- ----- --------- MAX_DUAL_SOURCE_DRAW_BUFFERS Z+ GetIntegerv 1 Maximum number of 4.1.8 - active draw buffers when using dual-source blending Example Use Cases There are several potential uses for this functionality. A first example is in the implementation of sub-pixel accurate font rendering algorithms. Given a known layout of pixel elements (red, green and blue components), coverage may be calculated independently for each element and passed to the blender in the second source color as a per-channel opacity. To use this mode, use the following blend functions: glBlendFunc(GL_SRC1_COLOR, GL_ONE_MINUS_SRC1_COLOR); As a second example, consider a partially reflective colored glass window. It will attenuate light passing through it, and reflect some of the light that strikes it. Using an appropriate combination of functions, this effect may be simulated in a single pass using only fixed-function blending hardware. In this case, the following blend functions may be used: glBlendFunc(GL_SRC_ALPHA, GL_SRC1_COLOR); Issues 1) Should the new tokens be SRC1_COLOR and SRC2_COLOR (1-based), or be SRC0_COLOR and SRC1_COLOR. RESOLVED: Indices in OpenGL are generally zero based. These follow suit. 2) What happens when rendering using a dual-source blend function using fixed-function? RESOLVED: There is no reasonable way to generate the second source color for blending using fixed-function fragment processing. However, as it is possible to set the blend function and then enable a shader, there isn't really a clean way to report an error. Therefore, we allow it, but leave the result undefined. 2a) Can't we use an existing output from fixed function, like back color, to make this work? DISCUSSION: We could relabel things. For example, make the front color be the first input to blending and the back color the second input. This kind of thing would come at the cost of lost fixed function capability, possible ambiguity and added complexity in the fixed function specification. The new functionality in this extension is most useful when reading data from multiple textures or other complex sources that would just be too complex to express with fixed function processing. For these reasons, rendering through dual-source blending functions using the fixed function pipeline is not supported and will produce undefined results. 2b) Then why write this against OpenGL 2.1 which includes fixed-function? Why not write against OpenGL 3.x that only supports shaders anyway? DISCUSSION: Because this extension adds functionality to existing extensions and those are written against OpenGL 2.1. Furthermore, the functionality described here does not rely on any core feature provided by OpenGL 3.x and can be easily built upon and used in implementations of OpenGL 2.1 or earlier versions of the OpenGL Specification. RESOLVED: Updated to stand against OpenGL 3.2, but kept the fixed function issues in the spec. 3) Why is this not orthogonal and interoperable with ARB_draw_buffers? RESOLVED: This is functionality that has existed in hardware for some time and been made available via other graphics APIs. In some hardware and APIs, the second color input from the shader is actually what would have been written to draw buffer 1. This is the functionality that is guaranteed to be universally supported. This extension does not preclude use with multiple draw buffers except exclusion through implementation defined limits. If future hardware supports multiple color outputs simultaneously to multiple draw buffers, it can simply advertise higher limits. 4) Can we not add an implementation state query to find out if it's available with multiple draw buffers? RESOLVED: Done. Query MAX_DUAL_SOURCE_DRAW_BUFFERS. If this returns the same value as MAX_DRAW_BUFFERS then the functions are orthogonal. If this returns 1, then they cannot be used together. If it returns some value between 1 and MAX_DRAW_BUFFERS, then dual-source blending may consume some additional hardware routing resources, but can be used with multiple draw buffers provided the MAX_DUAL_SOURCE_DRAW_BUFFERS limit is not exceeded. 5) Should there also be a Link error if the fragment shader uses both an index=1 output below MAX and an index=0 output greater than or equal to MAX? The quoted begin-time error leaves open the possibility of an app doing something like BindFragDataLocationIndexed(colorNumber=0, index=0) + (colorNumber=0, index=1) + (colorNumber=1, index=0), then rendering without using the src1 blend functions. If an implementation aliases index=1 onto other index=0 outputs, then it wouldn't be able to handle that case. DISCUSSION: The begin time error language states '... if any draw buffer has a blend function requiring the second color input ...'. This means that the outputs can be bound to non-zero indices, but if the blend function does not consume that output, no error will be generated. In theory, an implementation could ignore output bound to color=0, index=1 in this case and operate as if it were not there. However, it makes no sense for the linker to accept such a configuration of outputs because the underlying hardware may not be able to support it. Therefore, we can generate a link time error, thus eliminating this begin-time check and potentially improving run-time performance. Revision History Rev. Date Author Changes ---- -------- -------- ----------------------------------------- 13 05/22/2015 mjk Fix misspellings 12 02/05/2010 istewart Add interactions with NV_gpu_program5. 11 01/26/2010 pbrown Assign enum values. 10 01/14/2010 pbrown Add spec language allowing for a link error if explicit output bindings don't leave enough space for array outputs. Clarify that any automatic assignments for fragment outputs will use color index zero. 9 12/10/2009 Jon Leech Fix typos in blending equation table, remove ARB suffixes for core 3.3 inclusion, clean up "GL_TOKEN" vs. "the value of GL_TOKEN". 8 11/19/2009 gsellers Remove SRC0_COLOR etc. enums, use old ones instead. Use previously defined value for SRC1_ALPHA. Update text to match. 7 10/26/2009 gsellers Change BindFragDataLocationIndexedARB to take a numerical index instead of an enum. Clarify behavior in several places. Add issue 5. 6 10/20/2009 gsellers Update to diff to OpenGL 3.2 (Compatibility) spec. Add BindFragDataLocationIndexedARB and GetFragDataIndexARB. Remove idea of making shader outputs arrays. Define Begin time error when blend func is SRC1_* for FBO with >= MAX_DUAL_SOURCE_DRAW_BUFFERS draw buffers. 5 05/21/2009 gsellers Clarify meaning of MAX_DUAL_SOURCE_BUFFERS_ARB. Clarify the (lack of) interaction with fixed function fragment processing and further justify lack of support (Issues 2a and 2b). Clarify modification to state. 4 05/19/2009 gsellers Allow simultaneous use of ARB_draw_buffers with this extension; add MAX_DUAL_SOURCE_DRAW_BUFFERS_ARB. Document interaction with ARB_draw_buffers_blend. 3 05/19/2009 gsellers Remove access via gl_FragData, replace with user defined output varyings. 2 05/15/2009 gsellers Minor cleanup. Add usage examples. 1 05/14/2009 gsellers Initial draft