Kaynağa Gözat

Add luminance mode to posterization

Jakub Ciemała 2 hafta önce
ebeveyn
işleme
45388448cf

+ 42 - 3
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Effects/PosterizationNode.cs

@@ -12,23 +12,52 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Effects;
 public class PosterizationNode : RenderNode, IRenderInput
 {
     public RenderInputProperty Background { get; }
+    public InputProperty<PosterizationMode> Mode { get; }
     public InputProperty<int> Levels { get; }
     
     private Paint paint;
     private Shader shader;
     
     private Shader? lastImageShader;
+    private PosterizationMode? lastMode = null;
     private VecI lastDocumentSize;
     
     private string shaderCode = """
                                  uniform shader iImage;
+                                 uniform int iMode;
                                  uniform float iLevels;
-
+                                 
+                                 half posterize(half value, float levels) {
+                                     return clamp(floor(value * (levels - 1) + 0.5) / (levels - 1), 0.0, 1.0);
+                                 }
+                                 
+                                 half4 posterizeRgb(half4 color, float levels) {
+                                     return half4(
+                                         posterize(color.r, levels),
+                                         posterize(color.g, levels),
+                                         posterize(color.b, levels),
+                                         color.a
+                                     );
+                                 }
+                                 
+                                 half4 posterizeLuminance(half4 color, float levels) {
+                                     half lum = dot(color.rgb, half3(0.299, 0.587, 0.114));
+                                     half posterizedLum = posterize(lum, levels);
+                                     return half4(posterizedLum, posterizedLum, posterizedLum, color.a);
+                                 }
+                                 
                                  half4 main(float2 uv)
                                  {
                                     half4 color = iImage.eval(uv);
-                                    half3 posterized = floor(color.rgb * iLevels) / iLevels;
-                                    return half4(posterized, color.a);
+                                    half4 result;
+                                    
+                                    if(iMode == 0) {
+                                        result = posterizeRgb(color, iLevels);
+                                    } else if(iMode == 1) {
+                                        result = posterizeLuminance(color, iLevels);
+                                    } 
+                                    
+                                    return result;
                                  }
                                  """;
 
@@ -37,6 +66,7 @@ public class PosterizationNode : RenderNode, IRenderInput
     public PosterizationNode()
     {
         Background = CreateRenderInput("Background", "BACKGROUND");
+        Mode = CreateInput("Mode", "MODE", PosterizationMode.Rgb);
         Levels = CreateInput("Levels", "LEVELS", 8)
             .WithRules(v => v.Min(2).Max(256));
 
@@ -48,9 +78,11 @@ public class PosterizationNode : RenderNode, IRenderInput
     {
         base.OnExecute(context);
         lastDocumentSize = context.RenderOutputSize;
+        lastMode = Mode.Value;
         
         Uniforms uniforms = new Uniforms();
         uniforms.Add("iImage", new Uniform("iImage", lastImageShader));
+        uniforms.Add("iMode", new Uniform("iMode", (int)Mode.Value));
         uniforms.Add("iLevels", new Uniform("iLevels", (float)Levels.Value));
         shader?.Dispose();
         shader = Shader.Create(shaderCode, uniforms, out _);
@@ -71,6 +103,7 @@ public class PosterizationNode : RenderNode, IRenderInput
 
         Uniforms uniforms = new Uniforms();
         uniforms.Add("iImage", new Uniform("iImage", lastImageShader));
+        uniforms.Add("iMode", new Uniform("iMode", (int)Mode.Value));
         uniforms.Add("iLevels", new Uniform("iLevels", (float)Levels.Value));
         shader = shader.WithUpdatedUniforms(uniforms);
         paint.Shader = shader;
@@ -98,3 +131,9 @@ public class PosterizationNode : RenderNode, IRenderInput
         return new PosterizationNode();
     }
 }
+
+public enum PosterizationMode
+{
+    Rgb = 0,
+    Luminance = 1,
+}