674 lines
20 KiB
C#
674 lines
20 KiB
C#
|
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));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|