123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
- namespace PixiEditor.DrawingApi.Core.Shaders.Generation;
- public class BuiltInFunctions
- {
- private readonly List<BuiltInFunctionType> usedFunctions = new(Enum.GetValues(typeof(BuiltInFunctionType)).Length);
- public Expression GetHslToRgb(Expression hsla)
- {
- Require(BuiltInFunctionType.HslToRgb);
-
- return new Expression($"{nameof(HslToRgb)}({hsla.ExpressionValue})");
- }
- public Expression GetRgbToHsl(Expression rgba)
- {
- Require(BuiltInFunctionType.RgbToHsl);
- return new Expression($"{nameof(RgbToHsl)}({rgba.ExpressionValue})");
- }
- public Expression GetHslToRgb(Expression h, Expression s, Expression l, Expression a) =>
- GetHslToRgb(Half4.Constructor(h, s, l, a));
-
- public string BuildFunctions()
- {
- var builder = new StringBuilder();
- AppendIf(BuiltInFunctionType.HueToRgb, HueToRgb);
- AppendIf(BuiltInFunctionType.RgbToHcv, RgbToHcv);
-
- AppendIf(BuiltInFunctionType.HslToRgb, HslToRgb);
- AppendIf(BuiltInFunctionType.RgbToHsl, RgbToHsl);
-
- return builder.ToString();
- void AppendIf(BuiltInFunctionType type, string source)
- {
- if (usedFunctions.Contains(type))
- {
- builder.AppendLine(source);
- }
- }
- }
- private void Require(BuiltInFunctionType type)
- {
- if (usedFunctions.Contains(type))
- {
- return;
- }
- switch (type)
- {
- case BuiltInFunctionType.HslToRgb:
- Require(BuiltInFunctionType.HueToRgb);
- break;
- case BuiltInFunctionType.RgbToHsl:
- Require(BuiltInFunctionType.RgbToHcv);
- break;
- }
- usedFunctions.Add(type);
- }
- // Taken from here https://www.shadertoy.com/view/4dKcWK
- 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.);
- }
- """;
-
- 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 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 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
- {
- HueToRgb,
- RgbToHcv,
- RgbToHsl,
- HslToRgb,
- RgbToHsv,
- HsvToRgb
- }
- }
|