Difference between revisions of "BlendMode Formulas"
Antoniomoder (talk | contribs) m (readability) |
(Updated for 0.10.0.) |
||
Line 1: | Line 1: | ||
− | + | Equations used when blending drawn content with the screen or active [[Canvas]]. | |
− | + | Color components are generally in the range of [0, 1] rather than [0, 255] for the purposes of these equations. Results are clamped to [0, 1] except when a [[Canvas]] is active that has a floating-point / HDR [[CanvasFormat|format]]. | |
− | |||
− | |||
Description: | Description: | ||
− | *'''dst''' - existing color in the | + | *'''dst''' - existing color in the screen. |
− | *'''src''' - | + | *'''src''' - the color of the drawn object (the color output by the pixel shader, or the global color multiplied by the texture's color – if any, if no shader is used.) |
*'''res''' - resulting color. | *'''res''' - resulting color. | ||
Line 15: | Line 13: | ||
== alpha == | == alpha == | ||
− | === [[0.9.0]] and | + | === "alphamultiply" [[BlendAlphaMode|alpha mode]] === |
+ | |||
+ | res.r = dst.r * (1 - src.a) + src.r * src.a | ||
+ | res.g = dst.g * (1 - src.a) + src.g * src.a | ||
+ | res.b = dst.b * (1 - src.a) + src.b * src.a | ||
+ | res.a = dst.a * (1 - src.a) + src.a | ||
+ | |||
+ | === "premultiplied" [[BlendAlphaMode|alpha mode]] === | ||
+ | |||
+ | res.r = dst.r * (1 - src.a) + src.r | ||
+ | res.g = dst.g * (1 - src.a) + src.g | ||
+ | res.b = dst.b * (1 - src.a) + src.b | ||
+ | res.a = dst.a * (1 - src.a) + src.a | ||
+ | |||
+ | == add == | ||
+ | |||
+ | === "alphamultiply" [[BlendAlphaMode|alpha mode]] === | ||
+ | |||
+ | res.r = dst.r + (src.r * src.a) | ||
+ | res.g = dst.g + (src.g * src.a) | ||
+ | res.b = dst.b + (src.b * src.a) | ||
+ | res.a = dst.a | ||
+ | |||
+ | === "premultiplied" [[BlendAlphaMode|alpha mode]] === | ||
+ | |||
+ | res.r = dst.r + src.r | ||
+ | res.g = dst.g + src.g | ||
+ | res.b = dst.b + src.b | ||
+ | res.a = dst.a | ||
+ | |||
+ | == subtract == | ||
+ | |||
+ | === "alphamultiply" [[BlendAlphaMode|alpha mode]] === | ||
+ | |||
+ | res.r = dst.r - (src.r * src.a) | ||
+ | res.g = dst.g - (src.g * src.a) | ||
+ | res.b = dst.b - (src.b * src.a) | ||
+ | res.a = dst.a | ||
+ | |||
+ | === "premultiplied" [[BlendAlphaMode|alpha mode]] === | ||
+ | |||
+ | res.r = dst.r - src.r | ||
+ | res.g = dst.g - src.g | ||
+ | res.b = dst.b - src.b | ||
+ | res.a = dst.a | ||
+ | |||
+ | == replace == | ||
+ | |||
+ | === "alphamultiply" [[BlendAlphaMode|alpha mode]] === | ||
+ | |||
+ | res.r = src.r * src.a | ||
+ | res.g = src.g * src.a | ||
+ | res.b = src.b * src.a | ||
+ | res.a = src.a | ||
+ | |||
+ | === "premultiplied" [[BlendAlphaMode|alpha mode]] === | ||
+ | |||
+ | res.r = src.r | ||
+ | res.g = src.g | ||
+ | res.b = src.b | ||
+ | res.a = src.a | ||
+ | |||
+ | == multiply (both [[BlendAlphaMode|alpha modes]]) == | ||
+ | |||
+ | res.r = src.r * dst.r | ||
+ | res.g = src.g * dst.g | ||
+ | res.b = src.b * dst.b | ||
+ | res.a = src.a * dst.a | ||
+ | |||
+ | == screen == | ||
+ | |||
+ | Note: The math for this blend mode is not completely correct when using the "alphamultiply" alpha mode. Prefer the "premultiplied" variant (and be sure your content has its RGB multiplied by its alpha at some point before blending), when possible. | ||
+ | |||
+ | === "alphamultiply" [[BlendAlphaMode|alpha mode]] === | ||
+ | |||
+ | res.r = dst.r * (1 - src.r) + (src.r * src.a) | ||
+ | res.g = dst.g * (1 - src.g) + (src.g * src.a) | ||
+ | res.b = dst.b * (1 - src.b) + (src.b * src.a) | ||
+ | res.a = dst.a * (1 - src.a) + src.a | ||
+ | |||
+ | === "premultiplied" [[BlendAlphaMode|alpha mode]] === | ||
+ | |||
+ | res.r = dst.r * (1 - src.r) + src.r | ||
+ | res.g = dst.g * (1 - src.g) + src.g | ||
+ | res.b = dst.b * (1 - src.b) + src.b | ||
+ | res.a = dst.a * (1 - src.a) + src.a | ||
+ | |||
+ | == Older Versions == | ||
+ | |||
+ | === alpha ([[0.9.0]], [[0.9.1]], and [[0.9.2]]) === | ||
res.r = dst.r * (1 - src.a) + src.r * src.a | res.r = dst.r * (1 - src.a) + src.r * src.a | ||
Line 22: | Line 109: | ||
res.a = dst.a * (1 - src.a) + src.a | res.a = dst.a * (1 - src.a) + src.a | ||
− | === 0.8.0 and older | + | === alpha ([[0.8.0]] and older) === |
res.r = dst.r * (1 - src.a) + src.r * src.a | res.r = dst.r * (1 - src.a) + src.r * src.a | ||
Line 29: | Line 116: | ||
res.a = dst.a * (1 - src.a) + src.a * src.a | res.a = dst.a * (1 - src.a) + src.a * src.a | ||
− | == premultiplied == | + | === premultiplied ([[0.9.2]] and older) === |
res.r = dst.r * (1 - src.a) + src.r | res.r = dst.r * (1 - src.a) + src.r | ||
Line 36: | Line 123: | ||
res.a = dst.a * (1 - src.a) + src.a | res.a = dst.a * (1 - src.a) + src.a | ||
− | == screen == | + | === screen ([[0.9.2]] and older) === |
res.r = dst.r * (1 - src.r) + src.r | res.r = dst.r * (1 - src.r) + src.r | ||
Line 43: | Line 130: | ||
res.a = dst.a * (1 - src.a) + src.a | res.a = dst.a * (1 - src.a) + src.a | ||
− | == additive == | + | === additive ([[0.9.2]] and older) === |
res.r = dst.r + (src.r * src.a) | res.r = dst.r + (src.r * src.a) | ||
Line 50: | Line 137: | ||
res.a = dst.a + (src.a * src.a) | res.a = dst.a + (src.a * src.a) | ||
− | == subtractive == | + | === subtractive ([[0.9.2]] and older) === |
res.r = dst.r - src.r * src.a | res.r = dst.r - src.r * src.a | ||
Line 57: | Line 144: | ||
res.a = dst.a - src.a * src.a | res.a = dst.a - src.a * src.a | ||
− | == multiplicative | + | === multiplicative ([[0.9.0]], [[0.9.1]], and [[0.9.2]]) === |
− | |||
− | |||
res.r = src.r * dst.r | res.r = src.r * dst.r | ||
Line 66: | Line 151: | ||
res.a = src.a * dst.a | res.a = src.a * dst.a | ||
− | === 0.8.0 and older | + | === multiplicative ([[0.8.0]] and older) === |
res.r = dst.r * (1 - src.a) + src.r * dst.r | res.r = dst.r * (1 - src.a) + src.r * dst.r | ||
Line 73: | Line 158: | ||
res.a = dst.a * (1 - src.a) + src.a * dst.a | res.a = dst.a * (1 - src.a) + src.a * dst.a | ||
− | == replace == | + | === replace ([[0.9.2]] and older) === |
res.r = src.r | res.r = src.r | ||
Line 79: | Line 164: | ||
res.b = src.b | res.b = src.b | ||
res.a = src.a | res.a = src.a | ||
− | |||
− | |||
− | |||
== See Also == | == See Also == | ||
* [[BlendMode]] | * [[BlendMode]] |
Revision as of 21:22, 16 December 2015
Equations used when blending drawn content with the screen or active Canvas.
Color components are generally in the range of [0, 1] rather than [0, 255] for the purposes of these equations. Results are clamped to [0, 1] except when a Canvas is active that has a floating-point / HDR format.
Description:
- dst - existing color in the screen.
- src - the color of the drawn object (the color output by the pixel shader, or the global color multiplied by the texture's color – if any, if no shader is used.)
- res - resulting color.
Contents
- 1 alpha
- 2 add
- 3 subtract
- 4 replace
- 5 multiply (both alpha modes)
- 6 screen
- 7 Older Versions
- 7.1 alpha (0.9.0, 0.9.1, and 0.9.2)
- 7.2 alpha (0.8.0 and older)
- 7.3 premultiplied (0.9.2 and older)
- 7.4 screen (0.9.2 and older)
- 7.5 additive (0.9.2 and older)
- 7.6 subtractive (0.9.2 and older)
- 7.7 multiplicative (0.9.0, 0.9.1, and 0.9.2)
- 7.8 multiplicative (0.8.0 and older)
- 7.9 replace (0.9.2 and older)
- 8 See Also
alpha
"alphamultiply" alpha mode
res.r = dst.r * (1 - src.a) + src.r * src.a res.g = dst.g * (1 - src.a) + src.g * src.a res.b = dst.b * (1 - src.a) + src.b * src.a res.a = dst.a * (1 - src.a) + src.a
"premultiplied" alpha mode
res.r = dst.r * (1 - src.a) + src.r res.g = dst.g * (1 - src.a) + src.g res.b = dst.b * (1 - src.a) + src.b res.a = dst.a * (1 - src.a) + src.a
add
"alphamultiply" alpha mode
res.r = dst.r + (src.r * src.a) res.g = dst.g + (src.g * src.a) res.b = dst.b + (src.b * src.a) res.a = dst.a
"premultiplied" alpha mode
res.r = dst.r + src.r res.g = dst.g + src.g res.b = dst.b + src.b res.a = dst.a
subtract
"alphamultiply" alpha mode
res.r = dst.r - (src.r * src.a) res.g = dst.g - (src.g * src.a) res.b = dst.b - (src.b * src.a) res.a = dst.a
"premultiplied" alpha mode
res.r = dst.r - src.r res.g = dst.g - src.g res.b = dst.b - src.b res.a = dst.a
replace
"alphamultiply" alpha mode
res.r = src.r * src.a res.g = src.g * src.a res.b = src.b * src.a res.a = src.a
"premultiplied" alpha mode
res.r = src.r res.g = src.g res.b = src.b res.a = src.a
multiply (both alpha modes)
res.r = src.r * dst.r res.g = src.g * dst.g res.b = src.b * dst.b res.a = src.a * dst.a
screen
Note: The math for this blend mode is not completely correct when using the "alphamultiply" alpha mode. Prefer the "premultiplied" variant (and be sure your content has its RGB multiplied by its alpha at some point before blending), when possible.
"alphamultiply" alpha mode
res.r = dst.r * (1 - src.r) + (src.r * src.a) res.g = dst.g * (1 - src.g) + (src.g * src.a) res.b = dst.b * (1 - src.b) + (src.b * src.a) res.a = dst.a * (1 - src.a) + src.a
"premultiplied" alpha mode
res.r = dst.r * (1 - src.r) + src.r res.g = dst.g * (1 - src.g) + src.g res.b = dst.b * (1 - src.b) + src.b res.a = dst.a * (1 - src.a) + src.a
Older Versions
alpha (0.9.0, 0.9.1, and 0.9.2)
res.r = dst.r * (1 - src.a) + src.r * src.a res.g = dst.g * (1 - src.a) + src.g * src.a res.b = dst.b * (1 - src.a) + src.b * src.a res.a = dst.a * (1 - src.a) + src.a
alpha (0.8.0 and older)
res.r = dst.r * (1 - src.a) + src.r * src.a res.g = dst.g * (1 - src.a) + src.g * src.a res.b = dst.b * (1 - src.a) + src.b * src.a res.a = dst.a * (1 - src.a) + src.a * src.a
premultiplied (0.9.2 and older)
res.r = dst.r * (1 - src.a) + src.r res.g = dst.g * (1 - src.a) + src.g res.b = dst.b * (1 - src.a) + src.b res.a = dst.a * (1 - src.a) + src.a
screen (0.9.2 and older)
res.r = dst.r * (1 - src.r) + src.r res.g = dst.g * (1 - src.g) + src.g res.b = dst.b * (1 - src.b) + src.b res.a = dst.a * (1 - src.a) + src.a
additive (0.9.2 and older)
res.r = dst.r + (src.r * src.a) res.g = dst.g + (src.g * src.a) res.b = dst.b + (src.b * src.a) res.a = dst.a + (src.a * src.a)
subtractive (0.9.2 and older)
res.r = dst.r - src.r * src.a res.g = dst.g - src.g * src.a res.b = dst.b - src.b * src.a res.a = dst.a - src.a * src.a
multiplicative (0.9.0, 0.9.1, and 0.9.2)
res.r = src.r * dst.r res.g = src.g * dst.g res.b = src.b * dst.b res.a = src.a * dst.a
multiplicative (0.8.0 and older)
res.r = dst.r * (1 - src.a) + src.r * dst.r res.g = dst.g * (1 - src.a) + src.g * dst.g res.b = dst.b * (1 - src.a) + src.b * dst.b res.a = dst.a * (1 - src.a) + src.a * dst.a
replace (0.9.2 and older)
res.r = src.r res.g = src.g res.b = src.b res.a = src.a