From d463b627982c8e9cd4f712d8b76f0f56d817f29e Mon Sep 17 00:00:00 2001 From: Equbuxu Date: Wed, 12 Aug 2026 22:20:33 +0300 Subject: [PATCH 1/2] Fix #1678 - introduce unpremultiplication and premultiplication to begin/end modify image --- .../Shaders/Generation/BuiltInFunctions.cs | 13 ++++++++++++ .../Shaders/Generation/ShaderBuilder.cs | 21 +++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) 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) From c38a8f0702a8ecc870148a0c9785500e239c8a4a Mon Sep 17 00:00:00 2001 From: Equbuxu Date: Wed, 12 Aug 2026 23:07:18 +0300 Subject: [PATCH 2/2] Fix #1680: make sure the 'color' in layout(color) isn't replaced when replacing name --- .../Implementations/SkiaShaderImplementation.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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)) {