# Additive blending with weighted-blended order independent transparency

I am trying to retrofit weighted blended OIT to my rendering pipeline and while it works well, producing convincing results, for normal alpha blending (based on the OVER) operator, I am struggling to make it support additive blending (for example Colour1 + Colour2 + Background Colour) correctly using the blending formula:

$$\frac{C_1 w_1 + C_2 w_2}{\alpha_1 w_1 + \alpha_2 w_2} \cdot \bigl(1 - (1 - \alpha_1)(1 - \alpha_2)\bigr) + \text{Bg} \cdot (1 - \alpha_1)(1 - \alpha_2)$$

I could hack it outputting weight values of 1 and very low alphas (eg 0.01), which would make it to sort of converge to additive blending, trouble is, this does not weight the colours at all and does not blend nicely with normal alpha blending.

I was wondering how people have tackled this problem.

I have worked with this specific formula for the OVER operator but not with additive blending. I'll use the paper's nomenclature in the following discussion:

$$C_f = \frac{\sum_{i=1}^{n}C_i \cdot w(z_i, \alpha_i)}{\sum_{i=1}^{n}\alpha_i \cdot w(z_i, \alpha_i)}(1 - \prod_{i=1}^{n}(1 - \alpha_i)) + C_0\prod_{i=1}^{n}(1 - \alpha_i)$$

This is not explicitly stated in the paper, but the term $$C_i$$ is the premultiplied-alpha color (i.e. color.rgb * color.a)

As described in the paper, the term $$C_0\prod_{i=1}^{n}(1 - \alpha_i)$$ provides the "revealage" of the background color. If all the transparent surfaces are transparent, the product will be 1 and the background will be fully visible. The rest of the equation provides an approximation of the result of sorting the transparent surfaces by distance and using the OVER operator with pre-multiplied alpha colors.

However, the equation for additive blending (using glBlendFunc(GL_SRC_ALPHA, GL_ONE) and glBlendEquation(GL_FUNC_ADD)) without weights is: $$C_f = \sum_{i=1}^{n}\alpha_iRGB_i + C_0$$

This equation is already order independent! In order to add weights to the transparent surfaces with a normalization step in the end, the equation can then be simplified to:

$$C_f = \frac{\sum_{i=1}^{n}C_i \cdot w(z_i, \alpha_i)}{\sum_{i=1}^{n}w(z_i, \alpha_i)} + C_0$$

If you'd rather keep the same equation as before, you can achieve the same result by changing the shader outputs in listing 3 to:

gl_FragData[0] = vec4(Ci, 1) * w(zi, ai);
gl_FragData[1] = vec4(0);


Use the following equation for blending $$\frac{\alpha_1 w_1 C_1 + \alpha_2 w_2 C_2}{\alpha_1 w_1 + \alpha_2 w_2}.(1-(1-\alpha_1)(1-\alpha_2)) + Bg.(1-\alpha_1)(1-\alpha_2)$$ Also note that $\alpha$ value must always be between $0$ and $1$

• This is not much different to the one above, is it? :-) The point is that you need to output really small alphas to keep as much of Bg as possible and rely on large scales of output Colours to compensate for the suppression that those alphas will cause to the accumulated colour. Making sure that the denominator is not zero as well. Commented Feb 3, 2017 at 9:02
• There is a difference. Note that the alpha is multiplied by the color in the numerator and that fixes the problem Commented Feb 3, 2017 at 20:03
• In order to help people assess whether to use this approach, could you add an explanation of why this solves the problem with the approach in the question? Commented Mar 5, 2017 at 13:38