diff --git a/src/Drawie.Backend.Core/Shaders/Generation/BuiltInFunctions.cs b/src/Drawie.Backend.Core/Shaders/Generation/BuiltInFunctions.cs index 9b30b31..7a34025 100644 --- a/src/Drawie.Backend.Core/Shaders/Generation/BuiltInFunctions.cs +++ b/src/Drawie.Backend.Core/Shaders/Generation/BuiltInFunctions.cs @@ -9,6 +9,8 @@ public partial class BuiltInFunctions private const string Epsilon = "1e-10"; + public Expression GetUnpremultiply(Expression rgbaHalf4) => Call(Unpremultiply, rgbaHalf4); + public Expression GetRgbToHsv(Expression rgba) => Call(RgbToHsv, rgba); public Expression GetRgbToHsl(Expression rgba) => Call(RgbToHsl, rgba); @@ -65,6 +67,17 @@ private void Require(IBuiltInFunction function) usedFunctions.Add(function); } + private static readonly BuiltInFunction Unpremultiply = new( + "half4 color", + nameof(Unpremultiply), + """ + if (color.a <= 0.0) { + return half4(0, 0, 0, 0); + } + return half4(color.rgb / color.a, color.a); + """ + ); + // Taken from here https://www.shadertoy.com/view/4dKcWK private static readonly BuiltInFunction HueToRgb = new( "float hue", diff --git a/src/Drawie.Backend.Core/Shaders/Generation/ShaderBuilder.cs b/src/Drawie.Backend.Core/Shaders/Generation/ShaderBuilder.cs index 1880ce6..e16ef8f 100644 --- a/src/Drawie.Backend.Core/Shaders/Generation/ShaderBuilder.cs +++ b/src/Drawie.Backend.Core/Shaders/Generation/ShaderBuilder.cs @@ -83,20 +83,29 @@ public SurfaceSampler AddOrGetSurface(DrawingSurface surface, ColorSampleMode sa public Half4 Sample(SurfaceSampler texName, Expression pos, bool normalizedCoordinates) { - string resultName = $"color_{GetUniqueNameNumber()}"; - Half4 result = new Half4(resultName); - _variables.Add(result); + string rawResultName = $"color_{GetUniqueNameNumber()}"; + Half4 rawResult = new Half4(rawResultName); + _variables.Add(rawResult); + + string unpremulResultName = $"color_{GetUniqueNameNumber()}"; + Half4 unpremulResult = new Half4(unpremulResultName); + _variables.Add(unpremulResult); + if (normalizedCoordinates) { _bodyBuilder.AppendLine( - $"half4 {resultName} = {texName.VariableName}.eval({pos.ExpressionValue} * iResolution);"); + $"half4 {rawResultName} = {texName.VariableName}.eval({pos.ExpressionValue} * iResolution);"); + _bodyBuilder.AppendLine( + $"half4 {unpremulResultName} = {Functions.GetUnpremultiply(rawResult).ExpressionValue};"); } else { - _bodyBuilder.AppendLine($"half4 {resultName} = {texName.VariableName}.eval({pos.ExpressionValue});"); + _bodyBuilder.AppendLine($"half4 {rawResultName} = {texName.VariableName}.eval({pos.ExpressionValue});"); + _bodyBuilder.AppendLine( + $"half4 {unpremulResultName} = {Functions.GetUnpremultiply(rawResult).ExpressionValue};"); } - return result; + return unpremulResult; } public void ReturnVar(Half4 colorValue, bool premultiply) diff --git a/src/Drawie.Backend.Skia/Implementations/SkiaShaderImplementation.cs b/src/Drawie.Backend.Skia/Implementations/SkiaShaderImplementation.cs index b67ca3e..2cf478d 100644 --- a/src/Drawie.Backend.Skia/Implementations/SkiaShaderImplementation.cs +++ b/src/Drawie.Backend.Skia/Implementations/SkiaShaderImplementation.cs @@ -553,6 +553,14 @@ internal static List DeclarationsFromEffect(string code, SKR return null; } + private static string RemoveLastOccurance(string text, string toRemove) + { + int index = text.LastIndexOf(toRemove, StringComparison.Ordinal); + return index < 0 ? + text : + text.Substring(0, index) + text.Substring(index + toRemove.Length); + } + private static bool TryDetectType(string lastString, string name, out UniformValueType? detectedType) { if (!lastString.Contains("uniform ", StringComparison.InvariantCultureIgnoreCase)) @@ -561,7 +569,7 @@ private static bool TryDetectType(string lastString, string name, out UniformVal return false; } - string nameLessBlock = lastString.Replace(name, string.Empty); + string nameLessBlock = RemoveLastOccurance(lastString, name); if (nameLessBlock.Contains("color", StringComparison.InvariantCultureIgnoreCase)) {