Browse Source

Added RGB <-> HSL to Combine and Separate color nodes

CPKreuz 11 months ago
parent
commit
b2878fc0bc

+ 21 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Context/FuncContext.cs

@@ -109,6 +109,27 @@ public class FuncContext
         
         
         return Builder.ConstructHalf4(r, g, b, a);
         return Builder.ConstructHalf4(r, g, b, a);
     }
     }
+    
+    public Half4 HsvaToRgba(Expression h, Expression s, Expression v, Expression a)
+    {
+        if (!HasContext && h is Float1 firstFloat && s is Float1 secondFloat && v is Float1 thirdFloat && a is Float1 fourthFloat)
+        {
+            Half4 constantHalf4 = new Half4("");
+            var hValue = firstFloat.ConstantValue * 360;
+            var sValue = secondFloat.ConstantValue * 100;
+            var vValue = thirdFloat.ConstantValue * 100;
+            byte aByte = fourthFloat.FullSizeByteConstant;
+            constantHalf4.ConstantValue = Color.FromHsv((float)hValue, (float)sValue, (float)vValue, aByte);
+            return constantHalf4;
+        }
+
+        if (Half4Float1Accessor.AllAccessSame(h, s, v, a, out var half4))
+        {
+            return Builder.AssignNewHalf4(Builder.Functions.GetHsvToRgb(half4));
+        }
+        
+        return Builder.AssignNewHalf4(Builder.Functions.GetHsvToRgb(h, s, v, a));
+    }
 
 
     public Half4 HslaToRgba(Expression h, Expression s, Expression l, Expression a)
     public Half4 HslaToRgba(Expression h, Expression s, Expression l, Expression a)
     {
     {

+ 10 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineColorNode.cs

@@ -36,6 +36,15 @@ public class CombineColorNode : Node
     {
     {
         var a = ctx.GetValue(A);
         var a = ctx.GetValue(A);
         
         
+        if (Mode.Value == CombineSeparateColorMode.HSV)
+        {
+            var h = ctx.GetValue(R);
+            var s = ctx.GetValue(G);
+            var v = ctx.GetValue(B);
+
+            return ctx.HsvaToRgba(h, s, v, a);
+        }
+
         if (Mode.Value == CombineSeparateColorMode.HSL)
         if (Mode.Value == CombineSeparateColorMode.HSL)
         {
         {
             var h = ctx.GetValue(R);
             var h = ctx.GetValue(R);
@@ -44,7 +53,7 @@ public class CombineColorNode : Node
 
 
             return ctx.HslaToRgba(h, s, l, a);
             return ctx.HslaToRgba(h, s, l, a);
         }
         }
-        
+
         var r = ctx.GetValue(R);
         var r = ctx.GetValue(R);
         var g = ctx.GetValue(G);
         var g = ctx.GetValue(G);
         var b = ctx.GetValue(B);
         var b = ctx.GetValue(B);

+ 22 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateColorNode.cs

@@ -42,11 +42,16 @@ public class SeparateColorNode : Node
     
     
     private Half4 GetColor(FuncContext ctx)
     private Half4 GetColor(FuncContext ctx)
     {
     {
+        if (Mode.Value == CombineSeparateColorMode.HSV)
+        {
+            return GetHsva(ctx);
+        }
+
         if (Mode.Value == CombineSeparateColorMode.HSL)
         if (Mode.Value == CombineSeparateColorMode.HSL)
         {
         {
             return GetHsla(ctx);
             return GetHsla(ctx);
         }
         }
-        
+
         Half4 target = null;
         Half4 target = null;
         if (lastContext == ctx)
         if (lastContext == ctx)
         {
         {
@@ -78,5 +83,21 @@ public class SeparateColorNode : Node
         Expression RgbToHslGetter() => ctx.Builder.Functions.GetRgbToHsl(ctx.GetValue(Color));
         Expression RgbToHslGetter() => ctx.Builder.Functions.GetRgbToHsl(ctx.GetValue(Color));
     }
     }
 
 
+    private Half4 GetHsva(FuncContext ctx)
+    {
+        if (!ctx.HasContext && ctx.GetValue(Color) is Half4 constantColor)
+        {
+            var variable = new Half4(string.Empty);
+            constantColor.ConstantValue.ToHsv(out float h, out float s, out float l);
+            variable.ConstantValue = new Color((byte)(h * 255), (byte)(s * 255), (byte)(l * 255), constantColor.ConstantValue.A);
+            
+            return variable;
+        }
+
+        return ctx.Builder.GetOrNewAttachedHalf4(this.GetHashCode(), Color.GetHashCode(), RgbToHsvGetter);
+
+        Expression RgbToHsvGetter() => ctx.Builder.Functions.GetRgbToHsv(ctx.GetValue(Color));
+    }
+
     public override Node CreateCopy() => new SeparateColorNode();
     public override Node CreateCopy() => new SeparateColorNode();
 }
 }

+ 81 - 37
src/PixiEditor.DrawingApi.Core/Shaders/Generation/BuiltInFunctions.cs

@@ -10,6 +10,26 @@ public class BuiltInFunctions
 {
 {
     private readonly List<BuiltInFunctionType> usedFunctions = new(Enum.GetValues(typeof(BuiltInFunctionType)).Length);
     private readonly List<BuiltInFunctionType> usedFunctions = new(Enum.GetValues(typeof(BuiltInFunctionType)).Length);
 
 
+    public Expression GetRgbToHsv(Expression rgba)
+    {
+        Require(BuiltInFunctionType.RgbToHsv);
+
+        return new Expression($"{nameof(RgbToHsv)}({rgba.ExpressionValue})");
+    }
+    
+    public Expression GetRgbToHsv(Expression r, Expression g, Expression b, Expression a) =>
+        GetRgbToHsv(Half4.Constructor(r, g, b, a));
+
+    public Expression GetHsvToRgb(Expression hsva)
+    {
+        Require(BuiltInFunctionType.HsvToRgb);
+
+        return new Expression($"{nameof(HsvToRgb)}({hsva.ExpressionValue})");
+    }
+    
+    public Expression GetHsvToRgb(Expression h, Expression s, Expression v, Expression a) =>
+        GetHsvToRgb(Half4.Constructor(h, s, v, a));
+
     public Expression GetHslToRgb(Expression hsla)
     public Expression GetHslToRgb(Expression hsla)
     {
     {
         Require(BuiltInFunctionType.HslToRgb);
         Require(BuiltInFunctionType.HslToRgb);
@@ -34,6 +54,9 @@ public class BuiltInFunctions
         AppendIf(BuiltInFunctionType.HueToRgb, HueToRgb);
         AppendIf(BuiltInFunctionType.HueToRgb, HueToRgb);
         AppendIf(BuiltInFunctionType.RgbToHcv, RgbToHcv);
         AppendIf(BuiltInFunctionType.RgbToHcv, RgbToHcv);
         
         
+        AppendIf(BuiltInFunctionType.HsvToRgb, HsvToRgb);
+        AppendIf(BuiltInFunctionType.RgbToHsv, RgbToHsv);
+
         AppendIf(BuiltInFunctionType.HslToRgb, HslToRgb);
         AppendIf(BuiltInFunctionType.HslToRgb, HslToRgb);
         AppendIf(BuiltInFunctionType.RgbToHsl, RgbToHsl);
         AppendIf(BuiltInFunctionType.RgbToHsl, RgbToHsl);
         
         
@@ -57,9 +80,11 @@ public class BuiltInFunctions
 
 
         switch (type)
         switch (type)
         {
         {
+            case BuiltInFunctionType.HsvToRgb:
             case BuiltInFunctionType.HslToRgb:
             case BuiltInFunctionType.HslToRgb:
                 Require(BuiltInFunctionType.HueToRgb);
                 Require(BuiltInFunctionType.HueToRgb);
                 break;
                 break;
+            case BuiltInFunctionType.RgbToHsv:
             case BuiltInFunctionType.RgbToHsl:
             case BuiltInFunctionType.RgbToHsl:
                 Require(BuiltInFunctionType.RgbToHcv);
                 Require(BuiltInFunctionType.RgbToHcv);
                 break;
                 break;
@@ -71,54 +96,73 @@ public class BuiltInFunctions
     // Taken from here https://www.shadertoy.com/view/4dKcWK
     // Taken from here https://www.shadertoy.com/view/4dKcWK
     private const string HueToRgb =
     private const string HueToRgb =
         $$"""
         $$"""
-        half3 {{nameof(HueToRgb)}}(float hue)
-        {
-            vec3 rgb = abs(hue * 6. - vec3(3, 2, 4)) * vec3(1, -1, -1) + vec3(-1, 2, 2);
-            return clamp(rgb, 0., 1.);
-        }
-        """;
+          half3 {{nameof(HueToRgb)}}(float hue)
+          {
+              half3 rgb = abs(hue * 6. - half3(3, 2, 4)) * half3(1, -1, -1) + half3(-1, 2, 2);
+              return clamp(rgb, 0., 1.);
+          }
+          """;
     
     
-    private const string HslToRgb = 
+    private const string RgbToHcv =
         $$"""
         $$"""
-        half4 {{nameof(HslToRgb)}}(half4 hsla)
-        {
-            half3 rgb = {{nameof(HueToRgb)}}(hsla.x);
-            float c = (1. - abs(2. * hsla.z - 1.)) * hsla.y;
-            return half4((rgb - 0.5) * c + hsla.z, hsla.w);
-        }
-        """;
-    
-    private const string RgbToHcv = 
+          half3 {{nameof(RgbToHcv)}}(half3 rgba)
+          {
+              half4 p = (rgba.g < rgba.b) ? half4(rgba.bg, -1., 2. / 3.) : half4(rgba.gb, 0., -1. / 3.);
+              half4 q = (rgba.r < p.x) ? half4(p.xyw, rgba.r) : half4(rgba.r, p.yzx);
+              float c = q.x - min(q.w, q.y);
+              float h = abs((q.w - q.y) / (6. * c) + q.z);
+              return half3(h, c, q.x);
+          }
+          """;
+
+    private const string RgbToHsv =
         $$"""
         $$"""
-        half3 {{nameof(RgbToHcv)}}(half3 rgba)
-        {
-            half4 p = (rgba.g < rgba.b) ? half4(rgba.bg, -1., 2. / 3.) : half4(rgba.gb, 0., -1. / 3.);
-            half4 q = (rgba.r < p.x) ? half4(p.xyw, rgba.r) : half4(rgba.r, p.yzx);
-            float c = q.x - min(q.w, q.y);
-            float h = abs((q.w - q.y) / (6. * c) + q.z);
-            return half3(h, c, q.x);
-        }
-        """;
+          half4 {{nameof(RgbToHsv)}}(half4 rgba)
+          {
+              half3 hcv = {{nameof(RgbToHcv)}}(rgba.xyz);
+              float s = hcv.y / (hcv.z);
+              return half4(hcv.x, s, hcv.z, rgba.w);
+          }
+          """;
 
 
-    private const string RgbToHsl = 
+    private const string HsvToRgb =
         $$"""
         $$"""
-        half4 {{nameof(RgbToHsl)}}(half4 rgba)
-        {
-            half3 hcv = {{nameof(RgbToHcv)}}(rgba.xyz);
-            half z = hcv.z - hcv.y * 0.5;
-            half s = hcv.y / (1. - abs(z * 2. - 1.));
-            return half4(hcv.x, s, z, rgba.w);
-        }
-        """;
+          half4 {{nameof(HsvToRgb)}}(half4 hsva)
+          {
+              half3 rgb = {{nameof(HueToRgb)}}(hsva.x);
+              return half4(((rgb - 1.) * hsva.y + 1.) * hsva.z, hsva.w);
+          }
+          """;
+
+    private const string HslToRgb = 
+        $$"""
+          half4 {{nameof(HslToRgb)}}(half4 hsla)
+          {
+              half3 rgb = {{nameof(HueToRgb)}}(hsla.x);
+              float c = (1. - abs(2. * hsla.z - 1.)) * hsla.y;
+              return half4((rgb - 0.5) * c + hsla.z, hsla.w);
+          }
+          """;
+
+    private const string RgbToHsl =
+        $$"""
+          half4 {{nameof(RgbToHsl)}}(half4 rgba)
+          {
+              half3 hcv = {{nameof(RgbToHcv)}}(rgba.xyz);
+              half z = hcv.z - hcv.y * 0.5;
+              half s = hcv.y / (1. - abs(z * 2. - 1.));
+              return half4(hcv.x, s, z, rgba.w);
+          }
+          """;
     
     
     enum BuiltInFunctionType
     enum BuiltInFunctionType
     {
     {
         HueToRgb,
         HueToRgb,
         RgbToHcv,
         RgbToHcv,
 
 
-        RgbToHsl,
-        HslToRgb,
         RgbToHsv,
         RgbToHsv,
-        HsvToRgb
+        HsvToRgb,
+        RgbToHsl,
+        HslToRgb
     }
     }
 }
 }