├── .media ├── oklab.png ├── srlab2.png ├── contextmenu.gif └── originalGradient.png ├── LICENSE.meta ├── README.md.meta ├── package.json.meta ├── Editor.meta ├── Runtime.meta ├── Editor ├── Editor.asmdef.meta ├── GradientColorSpaceContextMenu.cs.meta ├── Editor.asmdef └── GradientColorSpaceContextMenu.cs ├── Runtime ├── Runtime.asmdef.meta ├── Lab.cs.meta ├── Oklab.cs.meta ├── SRLAB2.cs.meta ├── GradientColorSpace.cs.meta ├── Runtime.asmdef ├── Lab.cs ├── Oklab.cs ├── SRLAB2.cs └── GradientColorSpace.cs ├── package.json ├── LICENSE └── README.md /.media/oklab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markeahogan/GradientColorSpace/HEAD/.media/oklab.png -------------------------------------------------------------------------------- /.media/srlab2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markeahogan/GradientColorSpace/HEAD/.media/srlab2.png -------------------------------------------------------------------------------- /.media/contextmenu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markeahogan/GradientColorSpace/HEAD/.media/contextmenu.gif -------------------------------------------------------------------------------- /.media/originalGradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markeahogan/GradientColorSpace/HEAD/.media/originalGradient.png -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4351d83aba58126499f6a7ab61d5700b 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e25d52953cf8754793c59da5e842041 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d5c3f9a73283e614681cd625e0856ad0 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 80e4cc25e4f0bcf49959cff67740abf7 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 67d65d159a38ea24ca65e1ff98790193 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b84d8bfbc7248348950e582e00150f0 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Runtime.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7167cb9366116574a933d185d6da0899 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Lab.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 14fcf875eb4c1eb44ad92c5974f66dc2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Oklab.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d06bed11f943a0b499c94dc0704c5a56 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/SRLAB2.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e3af8ae0f1d0e0f47af7d5bc89ffabd8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/GradientColorSpace.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cfa3f5d7ee863b04baf15cdf14883e66 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/GradientColorSpaceContextMenu.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9603155b404a1e5499c0e3ef2c17031a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Runtime.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PopupAsylum.GradientColorSpace", 3 | "rootNamespace": "", 4 | "references": [], 5 | "includePlatforms": [], 6 | "excludePlatforms": [], 7 | "allowUnsafeCode": false, 8 | "overrideReferences": false, 9 | "precompiledReferences": [], 10 | "autoReferenced": true, 11 | "defineConstraints": [], 12 | "versionDefines": [], 13 | "noEngineReferences": false 14 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.popupasylum.gradientcolorspace", 3 | "displayName": "Gradient Color Space", 4 | "version": "1.0.2", 5 | "unity": "2019.3", 6 | "description": "Provides functionality to break a simple UnityEngine.Gradient into a piecewise curve in other color spaces.", 7 | "keywords": [ 8 | "gradient", 9 | "color", 10 | "space", 11 | "colorspace", 12 | "oklab", 13 | "srlab2" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Editor/Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PopupAsylum.GradientColorSpace.Editor", 3 | "rootNamespace": "", 4 | "references": [ 5 | "GUID:7167cb9366116574a933d185d6da0899" 6 | ], 7 | "includePlatforms": [ 8 | "Editor" 9 | ], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [], 16 | "versionDefines": [], 17 | "noEngineReferences": false 18 | } -------------------------------------------------------------------------------- /Runtime/Lab.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace PopupAsylum.GradientColorSpace 4 | { 5 | public struct Lab 6 | { 7 | public float L; 8 | public float a; 9 | public float b; 10 | public float alpha; 11 | 12 | public Lab(float l, float a, float b, float alpha = 1) 13 | { 14 | L = l; 15 | this.a = a; 16 | this.b = b; 17 | this.alpha = alpha; 18 | } 19 | 20 | public static Lab Lerp(Lab a, Lab b, float t) 21 | { 22 | return new Lab() 23 | { 24 | L = Mathf.Lerp(a.L, b.L, t), 25 | a = Mathf.Lerp(a.a, b.a, t), 26 | b = Mathf.Lerp(a.b, b.b, t), 27 | alpha = Mathf.Lerp(a.alpha, b.alpha, t) 28 | }; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 markeahogan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gradient Color Space 2 | 3 | A tool to convert a simple Unity.Gradient into a peicewise gradient interpolated in another color space. 4 | Useful to create nice looking gradients and avoid 'muddy' or perceptionally incorrect interpolated colors. 5 | 6 | ## Installation 7 | 8 | Installation via the Unity Package Manager. 9 | 10 | ### OpenUPM 11 | 12 | 1. In Unity on the top toolbar, go to `Edit > Project Settings > Package Manager`. 13 | 2. Add a new Scoped Registry (or edit the existing OpenUPM entry) 14 | ```txt 15 | Name package.openupm.com 16 | URL https://package.openupm.com 17 | Scope(s) com.popupasylum.gradientcolorspace 18 | ``` 19 | 3. Click Save (or Apply) 20 | 4. Open `Window > Package Manager` 21 | 5. Next to the `+` icon, select `My Registries` 22 | 6. Select `Gradient Color Space` and click install on the bottom right. 23 | 24 | ### Git 25 | 26 | 1. In Unity on the top toolbar, go to `Window > Package Manager`. 27 | 2. Click the `+` icon and select `Add package from Git URL`. 28 | 3. Enter the Git URL of this repository `https://github.com/markeahogan/GradientColorSpace.git`. 29 | 30 | ## Gradient Conversion 31 | 32 | A Gradient with 2 keys can be converted into a piecewise gradient with the appearance of another color space using the `GradientColorSpace.ConvertGradient` method. It creates 6 keys between the first and last keys that are interpolated from the first to last color using the chosen color space. 33 | 34 | ##### Original Gradient 35 | ![Original Gradient](.media/originalGradient.png) 36 | ##### Oklab Conversion 37 | ![Oklab Conversion](.media/oklab.png) 38 | ##### SRLAB2 Conversion 39 | ![SRLAB2 Conversion](.media/srlab2.png) 40 | 41 | ## Context Menu 42 | 43 | Right-clicking a gradient property's label will show a 'Color Space' context menu, allowing quick conversion. 44 | 45 | ![Context Menu](.media/contextmenu.gif) 46 | -------------------------------------------------------------------------------- /Runtime/Oklab.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace PopupAsylum.GradientColorSpace 4 | { 5 | static class Oklab 6 | { 7 | public static Lab FromColor(Color color) 8 | { 9 | return FromLinearColor(color.linear); 10 | } 11 | 12 | public static Lab FromLinearColor(Color linearColor) 13 | { 14 | float l = 0.4122214708f * linearColor.r + 0.5363325363f * linearColor.g + 0.0514459929f * linearColor.b; 15 | float m = 0.2119034982f * linearColor.r + 0.6806995451f * linearColor.g + 0.1073969566f * linearColor.b; 16 | float s = 0.0883024619f * linearColor.r + 0.2817188376f * linearColor.g + 0.6299787005f * linearColor.b; 17 | 18 | float l_ = cbrtf(l); 19 | float m_ = cbrtf(m); 20 | float s_ = cbrtf(s); 21 | 22 | return new Lab( 23 | 0.2104542553f * l_ + 0.7936177850f * m_ - 0.0040720468f * s_, 24 | 1.9779984951f * l_ - 2.4285922050f * m_ + 0.4505937099f * s_, 25 | 0.0259040371f * l_ + 0.7827717662f * m_ - 0.8086757660f * s_, 26 | linearColor.a); 27 | } 28 | 29 | public static Color ToColor(Lab lab) 30 | { 31 | return ToLinearColor(lab).gamma; 32 | } 33 | 34 | public static Color ToLinearColor(Lab lab) 35 | { 36 | float l_ = lab.L + 0.3963377774f * lab.a + 0.2158037573f * lab.b; 37 | float m_ = lab.L - 0.1055613458f * lab.a - 0.0638541728f * lab.b; 38 | float s_ = lab.L - 0.0894841775f * lab.a - 1.2914855480f * lab.b; 39 | 40 | float l = l_ * l_ * l_; 41 | float m = m_ * m_ * m_; 42 | float s = s_ * s_ * s_; 43 | 44 | return new Color( 45 | +4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s, 46 | -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s, 47 | -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s, 48 | lab.alpha); 49 | } 50 | 51 | private static float cbrtf(float l) => Mathf.Pow(l, 1f / 3f); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Editor/GradientColorSpaceContextMenu.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace PopupAsylum.GradientColorSpace.Editor 6 | { 7 | /// 8 | /// Adds a 'Color Space' context menu to Gradient properties that will create a piecewise gradient in a different color space 9 | /// 10 | [InitializeOnLoad] 11 | public class GradientColorSpaceContextMenu 12 | { 13 | static GradientColorSpaceContextMenu() 14 | { 15 | EditorApplication.contextualPropertyMenu += OnPropertyContextMenu; 16 | } 17 | 18 | private static void OnPropertyContextMenu(GenericMenu menu, SerializedProperty property) 19 | { 20 | if (property.propertyType != SerializedPropertyType.Gradient) 21 | return; 22 | 23 | var propertyCopy = property.Copy(); 24 | menu.AddItem(new GUIContent("Color Space/sRGB"), false, () => 25 | { 26 | UpdateGradient(propertyCopy, ColorSpace.sRGB); 27 | }); 28 | menu.AddItem(new GUIContent("Color Space/Oklab"), false, () => 29 | { 30 | UpdateGradient(propertyCopy, ColorSpace.Oklab); 31 | }); 32 | menu.AddItem(new GUIContent("Color Space/SRLAB2"), false, () => 33 | { 34 | UpdateGradient(propertyCopy, ColorSpace.SRLAB2); 35 | }); 36 | } 37 | 38 | private static void UpdateGradient(SerializedProperty property, ColorSpace colorSpace) 39 | { 40 | Gradient g = GetGradient(property); 41 | 42 | if (!GradientColorSpace.IsSafeToConvert(g) && 43 | !EditorUtility.DisplayDialog("Gradient Color Space", 44 | "Gradient Color Space interpolates between the first and last keys, inbetween keys will be lost", 45 | "OK", "Cancel")) 46 | { 47 | return; 48 | } 49 | 50 | GradientColorSpace.ConvertGradient(g, colorSpace); 51 | SetGradient(property, g); 52 | property.serializedObject.ApplyModifiedProperties(); 53 | } 54 | 55 | static Gradient GetGradient(SerializedProperty property) 56 | { 57 | PropertyInfo propertyInfo = typeof(SerializedProperty).GetProperty("gradientValue", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 58 | return propertyInfo.GetValue(property, null) as Gradient; 59 | } 60 | 61 | static void SetGradient(SerializedProperty property, Gradient gradient) 62 | { 63 | PropertyInfo propertyInfo = typeof(SerializedProperty).GetProperty("gradientValue", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 64 | propertyInfo.SetValue(property, gradient); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Runtime/SRLAB2.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace PopupAsylum.GradientColorSpace 4 | { 5 | /// 6 | /// https://www.magnetkern.de/srlab2.html 7 | /// 8 | public static class SRLAB2 9 | { 10 | public static Lab FromColor(Color color) 11 | { 12 | float red = color.r; 13 | float green = color.g; 14 | float blue = color.b; 15 | float x, y, z; 16 | if (red <= 0.03928) red /= 12.92f; 17 | else red = pow((red + 0.055f) / 1.055f, 2.4f); 18 | if (green <= 0.03928) green /= 12.92f; 19 | else green = pow((green + 0.055f) / 1.055f, 2.4f); 20 | if (blue <= 0.03928) blue /= 12.92f; 21 | else blue = pow((blue + 0.055f) / 1.055f, 2.4f); 22 | x = 0.320530f * red + 0.636920f * green + 0.042560f * blue; 23 | y = 0.161987f * red + 0.756636f * green + 0.081376f * blue; 24 | z = 0.017228f * red + 0.108660f * green + 0.874112f * blue; 25 | if (x <= 216.0 / 24389.0) x *= 24389.0f / 2700.0f; 26 | else x = 1.16f * pow(x, 1.0f / 3.0f) - 0.16f; 27 | if (y <= 216.0 / 24389.0) y *= 24389.0f / 2700.0f; 28 | else y = 1.16f * pow(y, 1.0f / 3.0f) - 0.16f; 29 | if (z <= 216.0 / 24389.0) z *= 24389.0f / 2700.0f; 30 | else z = 1.16f * pow(z, 1.0f / 3.0f) - 0.16f; 31 | 32 | return new Lab(37.0950f * x + 62.9054f * y - 0.0008f * z, 33 | 663.4684f * x - 750.5078f * y + 87.0328f * z, 34 | 63.9569f * x + 108.4576f * y - 172.4152f * z, 35 | color.a); 36 | } 37 | 38 | public static Color ToColor(Lab lab) 39 | { 40 | float lightness = lab.L; 41 | float a = lab.a; 42 | float b = lab.b; 43 | float red, green, blue; 44 | float x, y, z, rd, gn, bl; 45 | x = 0.01f * lightness + 0.000904127f * a + 0.000456344f * b; 46 | y = 0.01f * lightness - 0.000533159f * a - 0.000269178f * b; 47 | z = 0.01f * lightness - 0.005800000f * b; 48 | if (x <= 0.08f) x *= 2700.0f / 24389.0f; 49 | else x = pow((x + 0.16f) / 1.16f, 3.0f); 50 | if (y <= 0.08f) y *= 2700.0f / 24389.0f; 51 | else y = pow((y + 0.16f) / 1.16f, 3.0f); 52 | if (z <= 0.08f) z *= 2700.0f / 24389.0f; 53 | else z = pow((z + 0.16f) / 1.16f, 3.0f); 54 | rd = 5.435679f * x - 4.599131f * y + 0.163593f * z; 55 | gn = -1.168090f * x + 2.327977f * y - 0.159798f * z; 56 | bl = 0.037840f * x - 0.198564f * y + 1.160644f * z; 57 | if (rd <= 0.00304f) red = rd * 12.92f; 58 | else red = 1.055f * pow(rd, 1.0f / 2.4f) - 0.055f; 59 | if (gn <= 0.00304f) green = gn * 12.92f; 60 | else green = 1.055f * pow(gn, 1.0f / 2.4f) - 0.055f; 61 | if (bl <= 0.00304f) blue = bl * 12.92f; 62 | else blue = 1.055f * pow(bl, 1.0f / 2.4f) - 0.055f; 63 | 64 | return new Color(red, green, blue, lab.alpha); 65 | } 66 | 67 | private static float pow(float x, float y) => Mathf.Pow(x, y); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Runtime/GradientColorSpace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace PopupAsylum.GradientColorSpace 5 | { 6 | /// 7 | /// Provides methods for converting a Gradient into a piecewise gradient interpolated in a different color space 8 | /// 9 | public static class GradientColorSpace 10 | { 11 | private const int MAX_KEYS_MINUS_ONE = 7; 12 | 13 | /// 14 | /// Determines if data/keys would be lost by converting the gradient 15 | /// 16 | /// The gradient to be converted 17 | /// Returns false if converting would cause data/keys to be lost 18 | public static bool IsSafeToConvert(Gradient gradient) 19 | { 20 | var keys = gradient.colorKeys; 21 | 22 | if (keys.Length == 2) { return true; } 23 | if (keys.Length != 8) { return false; } 24 | 25 | float expectedSpacing = (keys[7].time - keys[0].time)/7; 26 | for (int i = 1; i < 8; i++) 27 | { 28 | float diff = Mathf.Abs((keys[i].time - keys[i - 1].time) - expectedSpacing); 29 | if (diff > 0.001f) { return false; } 30 | } 31 | 32 | return true; 33 | } 34 | 35 | /// 36 | /// Converts a simple gradient into a piecewise gradient interpolated in a different color space 37 | /// 38 | /// Gradient to be converted, must have at least 2 keys, keys between the first and last will be discarded 39 | /// The color space to convert to 40 | public static void ConvertGradient(Gradient gradient, ColorSpace space) 41 | { 42 | var originalKeys = gradient.colorKeys; 43 | 44 | if (originalKeys.Length < 2) 45 | { 46 | throw new ArgumentException($"Gradient must have at least 2 color keys, found {originalKeys.Length}"); 47 | } 48 | 49 | var startKey = originalKeys[0]; 50 | var endKey = originalKeys[originalKeys.Length - 1]; 51 | if (space == ColorSpace.sRGB) 52 | { 53 | gradient.colorKeys = new GradientColorKey[] { startKey, endKey }; 54 | return; 55 | } 56 | 57 | var keys = originalKeys.Length == 8 ? originalKeys : new GradientColorKey[8]; 58 | keys[0] = startKey; 59 | keys[MAX_KEYS_MINUS_ONE] = endKey; 60 | 61 | switch (space) 62 | { 63 | case ColorSpace.Oklab: 64 | OklabGradient(startKey, endKey, keys); 65 | break; 66 | case ColorSpace.SRLAB2: 67 | SRLAB2Gradient(startKey, endKey, keys); 68 | break; 69 | default: 70 | throw new Exception($"Can't handle {space}"); 71 | } 72 | 73 | gradient.colorKeys = keys; 74 | } 75 | 76 | private static void OklabGradient(GradientColorKey startKey, GradientColorKey endKey, GradientColorKey[] keys) 77 | { 78 | Lab start = Oklab.FromColor(startKey.color); 79 | Lab end = Oklab.FromColor(endKey.color); 80 | 81 | for (int i = 1; i < MAX_KEYS_MINUS_ONE; i++) 82 | { 83 | float t = i / (float)MAX_KEYS_MINUS_ONE; 84 | var time = Mathf.Lerp(startKey.time, endKey.time, t); 85 | var col = Oklab.ToColor(Lab.Lerp(start, end, t)); 86 | keys[i] = new GradientColorKey(col, time); 87 | } 88 | } 89 | 90 | private static void SRLAB2Gradient(GradientColorKey startKey, GradientColorKey endKey, GradientColorKey[] keys) 91 | { 92 | Lab start = SRLAB2.FromColor(startKey.color); 93 | Lab end = SRLAB2.FromColor(endKey.color); 94 | 95 | for (int i = 1; i < MAX_KEYS_MINUS_ONE; i++) 96 | { 97 | float t = i / (float)MAX_KEYS_MINUS_ONE; 98 | var time = Mathf.Lerp(startKey.time, endKey.time, t); 99 | var col = SRLAB2.ToColor(Lab.Lerp(start, end, t)); 100 | keys[i] = new GradientColorKey(col, time); 101 | } 102 | } 103 | } 104 | 105 | public enum ColorSpace 106 | { 107 | sRGB, 108 | Oklab, 109 | SRLAB2 110 | } 111 | } 112 | --------------------------------------------------------------------------------