I finally managed to get someone to take a look at this. It is a result of the different colour spaces, however I'm not convinced that it's not a problem with Spine's Unity runtimes. (Not Spine itself, obviously.)
As I understand it, Unity's SpriteRenderer takes care of any colour space conversion under the hood. So whether you're using gamma or linear, it will represent a Sprite correctly when the colour is set. An important aspect of this is that you can use any shader you'd like with a Unity sprite, and the colour will be represented properly.
As Spine is intended to work in tandem with Unity sprites (I assume?), not doing this is not only disparate from the flow of Unity, but (if solved at the shader level) would require the use of different (or specialised) shaders to account for it. While it's not technically a "bug", I do believe it's an issue.
It can be solved at a code level, using a conversion:
static Color GammaToLinear(Color c){
return new Color(
Mathf.Pow(c.r, 2.2f),
Mathf.Pow(c.g, 2.2f),
Mathf.Pow(c.b, 2.2f),
c.a
);
}
However this comes with its own set of issues. For example, needing to ensure a backwards conversion is done when using GetColor(), as well as maintaining two Color values (one for Sprites, one for Spine). That seems cumbersome, and I don't believe it fits in with the flow of Unity?
But I'm open to other opinions.
I made some extension methods to manage the conversion, it works well and alleviates some of the problems I mentioned at the end:
#region Spine
public static void SetColor(this Slot slot, Color color, bool colorSpaceConvert) {
slot.SetColor(colorSpaceConvert && QualitySettings.activeColorSpace == ColorSpace.Linear ? GammaToLinear(color) : color);
}
static Color GammaToLinear(Color color){
return new Color(
Mathf.Pow(color.r, 2.2f),
Mathf.Pow(color.g, 2.2f),
Mathf.Pow(color.b, 2.2f),
color.a
);
}
public static Color GetColor(this Slot slot, bool colorSpaceConvert) {
return colorSpaceConvert && QualitySettings.activeColorSpace == ColorSpace.Linear ? LinearToGamma(slot.GetColor()) : slot.GetColor();
}
static Color LinearToGamma(Color color){
return new Color(
Mathf.Pow(color.r, 0.4545f),
Mathf.Pow(color.g, 0.4545f),
Mathf.Pow(color.b, 0.4545f),
color.a
);
}
#endregion
However more generally speaking, I believe Spine should attempt to integrate with Unity as smoothly as it can, which would include replicating Sprite behaviour where possible?