With the introduction of programmable blending units, the intuitive meaning of alpha being a measure of opaqueness doesn't always hold.
In the two-operand blend you have two contributing fragments:
- the source (what you're blending, the new fragment),
- the destination (what already exists in the spot you're blending to).
You have two independent blending equations, one for the colour components and one for the alpha. Your blend state controls parameters of those equations, relating the two inputs with the output.
result.rgb = ColorBlendOp(src.rgb * SrcBlendColor, dst.rgb * DestBlendColor);
result.a = AlphaBlendOp(src.a * SrcBlendAlpha, dst.a * DestBlendAlpha);
The blend operations are normally mathematical operations like add, subtract, reverse subtract, multiply, applying the operation to the two operands.
Your blend factors expands to constants or values related to the components of the source and destination fragments:
ZERO expand to literal
SRC_ALPHA expands to
INV_SRC_ALPHA expands to
DST_ALPHA expands to
- And so on...
In order to evaluate a blending equation, substitute the blend factors and operations with their mathematical expansion, plug in the values from your source and destination fragments, and evaluate the expression.
At no point here do we attach any particular meaning to alpha and the colour components, they're just constants in an equation. The interpretation of the resulting RGB+alpha is up to the application, not the blender.
For your set of parameters, we get the following equation pair (assuming alpha blending uses the same operation):
result.rgb = Add(src.rgb * 1, dst.rgb * 1);
result.a = Add(src.a * 0, dst.a * 0);
If you've got several blends to perform after each other, take the
a of the previous expression and use it as destination
a after each blend.
For an example of two things blended in turn onto a background, you've got:
final = blend(#2, blend(#1, background)))
or more explicit:
inter = blend(#1, background)
final = blend(#2, inter)