How to perform additive blending in Metal. What do these terms mean?

Forgive me, I dont really understand the basis of alpha blending. Like I know the formula but when it comes to the terms blending operation, source blend factor, and destination blend factor I am absolutely lost.

The goal is to do additive blending like in photoshop so black items would be invisible and items with any color would add their color resulting in an effect that pixels with many layers underneath are close to white.

The problem is I have no clue how to translate this to metal. For example this is how I am currently doing alpha blending (although this currently isnt working for whatever reason). What should I be doing for additive blending?

descriptor.colorAttachments[0].blendingEnabled = YES;
descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;

• What is stored in the frame buffer or what is the clear color? – Matthias Aug 27 '18 at 17:04
• The clear color is black. What do you mean what is stored in the frame buffer? – J.Doe Aug 27 '18 at 17:23
• You could already start with some kind of image generated during a previous pass. – Matthias Aug 27 '18 at 17:30
• So you basically want to use the following blend equation dst.rgba <- src.rgba + dst.rgba? The more non-black draws to a pixel, the larger the pixel color becomes (i.e. goes to white). – Matthias Aug 27 '18 at 17:32
• @Matthias Correct! – J.Doe Aug 27 '18 at 17:34

The “blend factors” are the amount that the specified component is multiplied by while blending. “Destination” is the existing content that’s being blended “on top of”, while “source” is the new content that’s being blended “onto” it. When the blend operation is set to “add”, the final pixel value is calculated like this:

value = source * sourceBlendFactor + destination * destinationBlendFactor


…so a blend factor of “one” means the value is used unchanged (multiplied by 1), “[x]Alpha” means the value is multiplied by the alpha value of x (source or destination), and “oneMinus[x]Alpha” means the value is multiplied by (1 - the alpha value of x).

For additive blending, you most likely want the following:

Objective-C:

descriptor.colorAttachments[0].blendingEnabled = YES;
descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne;
descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne;


Swift 5:

descriptor.colorAttachments.colorAttachments[0].isBlendingEnabled = true
descriptor.colorAttachments.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
descriptor.colorAttachments.colorAttachments[0].sourceAlphaBlendFactor = .one
descriptor.colorAttachments.colorAttachments[0].destinationRGBBlendFactor = .one
descriptor.colorAttachments.colorAttachments[0].destinationAlphaBlendFactor = .one


There’s a really helpful tool for visualizing the different options here—it’s written for OpenGL, but the Metal stuff works the same way.

• In Metal there is a blend factor of sourceColor as well as one called "one" whaw would source color look like? Would that just be the color squared or something? – J.Doe Aug 27 '18 at 17:47
• Yeah, exactly. There’s some interesting things you could do with that, but I haven’t seen it used much. You can make a “multiply” blend mode by setting the source blend mode to “destinationColor” and the destination one’s to “zero” (or vice versa). – Noah Witherspoon Aug 27 '18 at 17:52
• why do you set sourceRGBBlendFactor to BlendFactorSourceAlpha. Is this an error? – J.Doe Aug 28 '18 at 6:38
• No—it allows you to modulate the amount of color being added with the pixel’s alpha value, just like changing a Screen layer’s opacity in Photoshop. – Noah Witherspoon Aug 28 '18 at 15:14

Terminology

• The source color is the value written by the fragment/pixel shader.
• The destination color is the color from the image currently in the frame buffer (that will be overridden).

// The blend formula is defined as:
// (source.rgb * sourceRGBBlendFactor  )   rgbBlendOperation (destination.rgb * destinationRGBBlendFactor  )
// (source.a   * sourceAlphaBlendFactor) alphaBlendOperation (destination.a   * destinationAlphaBlendFactor)
// <=>
// (source.rgba * 1) + (destination.rgba * 1)

descriptor.colorAttachments[0].blendingEnabled             = YES;

If the clear color is equal to {0.0f,0.0f,0.0f,_} and we draw {0.1f,0.1f,0.1f,_} to the same pixel a couple of times, the pixel color eventually becomes {1.0f,1.0f,1.0f,_} (white). Drawing {0.0f,0.0f,0.0f,_} (black) has no effect. We do not care about the alphas.
• Since you said in the comments above that you want the following blend equation: dst.rgba <- src.rgba + dst.rgba which basically adds the new color to the old one (so you multiply by 1)? – Matthias Aug 27 '18 at 17:43
• @J.Doe It could also be a vector: you can multiply dst.rgba with src.rgba for instance and you can also multiply with a constant color. But for additive blending, you just want to do an addition. – Matthias Aug 27 '18 at 17:46