123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673 |
- using UnityEngine;
- using Unity.Burst;
-
- namespace UnityEditor.U2D.Aseprite
- {
- [BurstCompile]
- internal static class PixelBlends
- {
- [BurstCompile]
- public static void Normal(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- var inAlpha = inColor.a / 255f;
-
- outColor = new Color32
- {
- a = (byte)(inColor.a + prevOutColor.a * (1f - inAlpha))
- };
-
- var prevAlpha = (prevOutColor.a * (1f - inAlpha)) / 255f;
- var premultiplyAlpha = outColor.a > 0 ? 255f / outColor.a : 1f;
- outColor.r = (byte)((inColor.r * inAlpha + prevOutColor.r * prevAlpha) * premultiplyAlpha);
- outColor.g = (byte)((inColor.g * inAlpha + prevOutColor.g * prevAlpha) * premultiplyAlpha);
- outColor.b = (byte)((inColor.b * inAlpha + prevOutColor.b * prevAlpha) * premultiplyAlpha);
- }
-
- [BurstCompile]
- public static void Darken(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var darken = new Color32
- {
- r = inColor.r < prevOutColor.r ? inColor.r : prevOutColor.r,
- g = inColor.g < prevOutColor.g ? inColor.g : prevOutColor.g,
- b = inColor.b < prevOutColor.b ? inColor.b : prevOutColor.b,
- a = inColor.a
- };
-
- Normal(in prevOutColor, in darken, out outColor);
- }
-
- [BurstCompile]
- public static void Multiply(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var multiply = new Color32
- {
- r = MultiplyUnsignedByte(inColor.r, prevOutColor.r),
- g = MultiplyUnsignedByte(inColor.g, prevOutColor.g),
- b = MultiplyUnsignedByte(inColor.b, prevOutColor.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in multiply, out outColor);
- }
-
- [BurstCompile]
- public static void ColorBurn(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var burn = new Color32
- {
- r = BurnChannel(prevOutColor.r, inColor.r),
- g = BurnChannel(prevOutColor.g, inColor.g),
- b = BurnChannel(prevOutColor.b, inColor.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in burn, out outColor);
- }
-
- [BurstCompile]
- static byte BurnChannel(byte prevVal, byte inVal)
- {
- if (prevVal == 255)
- return prevVal;
- prevVal = (byte)(255 - prevVal);
- if (prevVal >= inVal)
- return 0;
-
- var div = DivideUnsignedByte(prevVal, inVal);
- return (byte)(255 - div);
- }
-
- [BurstCompile]
- public static void Lighten(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var lighten = new Color32
- {
- r = inColor.r > prevOutColor.r ? inColor.r : prevOutColor.r,
- g = inColor.g > prevOutColor.g ? inColor.g : prevOutColor.g,
- b = inColor.b > prevOutColor.b ? inColor.b : prevOutColor.b,
- a = inColor.a
- };
-
- Normal(in prevOutColor, in lighten, out outColor);
- }
-
- [BurstCompile]
- public static void Screen(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var multiply = new Color32
- {
- r = MultiplyUnsignedByte(inColor.r, prevOutColor.r),
- g = MultiplyUnsignedByte(inColor.g, prevOutColor.g),
- b = MultiplyUnsignedByte(inColor.b, prevOutColor.b)
- };
-
- var screen = new Color32
- {
- r = (byte)((inColor.r + prevOutColor.r) - multiply.r),
- g = (byte)((inColor.g + prevOutColor.g) - multiply.g),
- b = (byte)((inColor.b + prevOutColor.b) - multiply.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in screen, out outColor);
- }
-
- [BurstCompile]
- public static void ColorDodge(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var burn = new Color32
- {
- r = DodgeChannel(prevOutColor.r, inColor.r),
- g = DodgeChannel(prevOutColor.g, inColor.g),
- b = DodgeChannel(prevOutColor.b, inColor.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in burn, out outColor);
- }
-
- [BurstCompile]
- static byte DodgeChannel(byte prevVal, byte inVal)
- {
- if (prevVal == 0)
- return 0;
- inVal = (byte)(255 - inVal);
- if (prevVal >= inVal)
- return 255;
-
- var div = DivideUnsignedByte(prevVal, inVal);
- return div;
- }
-
- [BurstCompile]
- public static void Addition(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var addition = new Color32
- {
- r = (byte)Mathf.Min(inColor.r + prevOutColor.r, 255),
- g = (byte)Mathf.Min(inColor.g + prevOutColor.g, 255),
- b = (byte)Mathf.Min(inColor.b + prevOutColor.b, 255),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in addition, out outColor);
- }
-
- [BurstCompile]
- public static void Overlay(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var overlay = new Color32
- {
- r = HardLightChannel(inColor.r, prevOutColor.r),
- g = HardLightChannel(inColor.g, prevOutColor.g),
- b = HardLightChannel(inColor.b, prevOutColor.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in overlay, out outColor);
- }
-
- [BurstCompile]
- static byte HardLightChannel(byte valA, byte valB)
- {
- if (valB < 128)
- return MultiplyUnsignedByte(valA, (byte)(valB << 1));
- return ScreenUnsignedByte(valA, (byte)((valB << 1) - 255));
- }
-
- [BurstCompile]
- public static void SoftLight(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var overlay = new Color32
- {
- r = SoftLightChannel(prevOutColor.r, inColor.r),
- g = SoftLightChannel(prevOutColor.g, inColor.g),
- b = SoftLightChannel(prevOutColor.b, inColor.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in overlay, out outColor);
- }
-
- [BurstCompile]
- static byte SoftLightChannel(byte inA, byte inB)
- {
- var valA = inA / 255f;
- var valB = inB / 255f;
- float valC, final;
-
- if (valA <= 0.25f)
- valC = ((16 * valA - 12) * valA + 4) * valA;
- else
- valC = Mathf.Sqrt(valA);
-
- if (valB <= 0.5f)
- final = valA - (1f - 2f * valB) * valA * (1f - valA);
- else
- final = valA + (2f * valB - 1f) * (valC - valA);
-
- return (byte)(final * 255f + 0.5f);
- }
-
- [BurstCompile]
- public static void HardLight(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var overlay = new Color32
- {
- r = HardLightChannel(prevOutColor.r, inColor.r),
- g = HardLightChannel(prevOutColor.g, inColor.g),
- b = HardLightChannel(prevOutColor.b, inColor.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in overlay, out outColor);
- }
-
- [BurstCompile]
- public static void Difference(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var difference = new Color32
- {
- r = DifferenceChannel(prevOutColor.r, inColor.r),
- g = DifferenceChannel(prevOutColor.g, inColor.g),
- b = DifferenceChannel(prevOutColor.b, inColor.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in difference, out outColor);
- }
-
- [BurstCompile]
- static byte DifferenceChannel(byte valA, byte valB)
- {
- return (byte)Mathf.Abs(valA - valB);
- }
-
- [BurstCompile]
- public static void Exclusion(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var exclusion = new Color32
- {
- r = ExclusionChannel(prevOutColor.r, inColor.r),
- g = ExclusionChannel(prevOutColor.g, inColor.g),
- b = ExclusionChannel(prevOutColor.b, inColor.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in exclusion, out outColor);
- }
-
- [BurstCompile]
- static byte ExclusionChannel(byte valA, byte valB)
- {
- var valC = MultiplyUnsignedByte(valA, valB);
- return (byte)(valA + valB - 2 * valC);
- }
-
- [BurstCompile]
- public static void Subtract(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var subtract = new Color32
- {
- r = (byte)Mathf.Max(prevOutColor.r - inColor.r, 0),
- g = (byte)Mathf.Max(prevOutColor.g - inColor.g, 0),
- b = (byte)Mathf.Max(prevOutColor.b - inColor.b, 0),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in subtract, out outColor);
- }
-
- [BurstCompile]
- public static void Divide(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var divide = new Color32
- {
- r = DivideChannel(prevOutColor.r, inColor.r),
- g = DivideChannel(prevOutColor.g, inColor.g),
- b = DivideChannel(prevOutColor.b, inColor.b),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in divide, out outColor);
- }
-
- [BurstCompile]
- static byte DivideChannel(byte valA, byte valB)
- {
- if (valA == 0)
- return 0;
- else if (valA >= valB)
- return 255;
- else
- return DivideUnsignedByte(valA, valB);
- }
-
- [BurstCompile]
- public static void Hue(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var r = prevOutColor.r / 255f;
- var g = prevOutColor.g / 255f;
- var b = prevOutColor.b / 255f;
- var s = GetSaturation(r, g, b);
- var l = GetLuminosity(r, g, b);
-
- r = inColor.r / 255f;
- g = inColor.g / 255f;
- b = inColor.b / 255f;
-
- SetSaturation(ref r, ref g, ref b, s);
- SetLuminosity(ref r, ref g, ref b, l);
-
- var hue = new Color32()
- {
- r = (byte)Mathf.RoundToInt(r * 255f),
- g = (byte)Mathf.RoundToInt(g * 255f),
- b = (byte)Mathf.RoundToInt(b * 255f),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in hue, out outColor);
- }
-
- [BurstCompile]
- public static void Saturation(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var r = inColor.r / 255f;
- var g = inColor.g / 255f;
- var b = inColor.b / 255f;
- var s = GetSaturation(r, g, b);
-
- r = prevOutColor.r / 255f;
- g = prevOutColor.g / 255f;
- b = prevOutColor.b / 255f;
- var l = GetLuminosity(r, g, b);
-
- SetSaturation(ref r, ref g, ref b, s);
- SetLuminosity(ref r, ref g, ref b, l);
-
- var saturation = new Color32()
- {
- r = (byte)Mathf.RoundToInt(r * 255f),
- g = (byte)Mathf.RoundToInt(g * 255f),
- b = (byte)Mathf.RoundToInt(b * 255f),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in saturation, out outColor);
- }
-
- [BurstCompile]
- public static void ColorBlend(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var r = prevOutColor.r / 255f;
- var g = prevOutColor.g / 255f;
- var b = prevOutColor.b / 255f;
- var l = GetLuminosity(r, g, b);
-
- r = inColor.r / 255f;
- g = inColor.g / 255f;
- b = inColor.b / 255f;
-
- SetLuminosity(ref r, ref g, ref b, l);
-
- var color = new Color32()
- {
- r = (byte)Mathf.RoundToInt(r * 255f),
- g = (byte)Mathf.RoundToInt(g * 255f),
- b = (byte)Mathf.RoundToInt(b * 255f),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in color, out outColor);
- }
-
- [BurstCompile]
- public static void Luminosity(in Color32 prevOutColor, in Color32 inColor, out Color32 outColor)
- {
- outColor = new Color32();
-
- if (prevOutColor == Color.clear)
- {
- outColor = inColor;
- return;
- }
-
- var r = inColor.r / 255f;
- var g = inColor.g / 255f;
- var b = inColor.b / 255f;
- var l = GetLuminosity(r, g, b);
-
- r = prevOutColor.r / 255f;
- g = prevOutColor.g / 255f;
- b = prevOutColor.b / 255f;
-
- SetLuminosity(ref r, ref g, ref b, l);
-
- var luminosity = new Color32()
- {
- r = (byte)Mathf.RoundToInt(r * 255f),
- g = (byte)Mathf.RoundToInt(g * 255f),
- b = (byte)Mathf.RoundToInt(b * 255f),
- a = inColor.a
- };
-
- Normal(in prevOutColor, in luminosity, out outColor);
- }
-
- [BurstCompile]
- static byte MultiplyUnsignedByte(byte valA, byte valB)
- {
- const uint oneHalf = 0x80;
- const int gShift = 8;
- var valC = (int)((valA * valB) + oneHalf);
- return (byte)(((valC >> gShift) + valC) >> gShift);
- }
-
- [BurstCompile]
- static byte ScreenUnsignedByte(byte valA, byte valB)
- {
- return (byte)(valB + valA - MultiplyUnsignedByte(valB, valA));
- }
-
- [BurstCompile]
- static byte DivideUnsignedByte(byte valA, byte valB)
- {
- return (byte)((valA * 0xFF) / valB);
- }
-
- [BurstCompile]
- static float GetSaturation(float r, float g, float b)
- {
- return Mathf.Max(r, Mathf.Max(g, b)) - Mathf.Min(r, Mathf.Min(g, b));
- }
-
- [BurstCompile]
- static void SetSaturation(ref float r, ref float g, ref float b, float s)
- {
- ref var min = ref MinRef(ref r, ref MinRef(ref g, ref b));
- ref var mid = ref MidRef(ref r, ref g, ref b);
- ref var max = ref MaxRef(ref r, ref MaxRef(ref g, ref b));
-
- if (max > min)
- {
- mid = ((mid - min) * s) / (max - min);
- max = s;
- }
- else
- mid = max = 0;
-
- min = 0f;
- }
-
- [BurstCompile]
- static ref float MaxRef(ref float a, ref float b)
- {
- if (a > b)
- return ref a;
- return ref b;
- }
-
- [BurstCompile]
- static ref float MinRef(ref float a, ref float b)
- {
- if (a < b)
- return ref a;
- return ref b;
- }
-
- static ref float MidRef(ref float a, ref float b, ref float c)
- {
- if (a > b)
- {
- if (b > c)
- {
- return ref b;
- }
- if (a > c)
- return ref c;
- return ref a;
- }
- if (!(b > c))
- return ref b;
- if (c > a)
- return ref c;
- return ref a;
- }
-
- [BurstCompile]
- static float GetLuminosity(float r, float g, float b)
- {
- return (0.3f * r) + (0.59f * g) + (0.11f * b);
- }
-
- [BurstCompile]
- static void SetLuminosity(ref float r, ref float g, ref float b, float l)
- {
- var d = l - GetLuminosity(r, g, b);
- r += d;
- g += d;
- b += d;
- ClipColor(ref r, ref g, ref b);
- }
-
- [BurstCompile]
- static void ClipColor(ref float r, ref float g, ref float b)
- {
- var l = GetLuminosity(r, g, b);
- var n = Mathf.Min(r, Mathf.Min(g, b));
- var x = Mathf.Max(r, Mathf.Max(g, b));
-
- if (n < 0)
- {
- r = l + (((r - l) * l) / (l - n));
- g = l + (((g - l) * l) / (l - n));
- b = l + (((b - l) * l) / (l - n));
- }
-
- if (x > 1)
- {
- r = l + (((r - l) * (1 - l)) / (x - l));
- g = l + (((g - l) * (1 - l)) / (x - l));
- b = l + (((b - l) * (1 - l)) / (x - l));
- }
- }
- }
- }
|