Browse Source

Shader node somewhat works

flabbet 10 months ago
parent
commit
b97684a56a

+ 3 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Context/FuncContext.cs

@@ -6,6 +6,7 @@ using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Shaders.Generation;
 using PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
+using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.Numerics;
 using Expression = PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions.Expression;
 
@@ -51,9 +52,9 @@ public class FuncContext
         SamplePosition = Builder.ConstructFloat2(OriginalPosition.X, OriginalPosition.Y); 
     }
 
-    public Half4 SampleTexture(Texture imageValue, Float2 pos)
+    public Half4 SampleSurface(DrawingSurface surface, Float2 pos)
     {
-        TextureSampler texName = Builder.AddOrGetTexture(imageValue);
+        SurfaceSampler texName = Builder.AddOrGetSurface(surface);
         return Builder.Sample(texName, pos);
     }
 

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MergeNode.cs

@@ -53,13 +53,13 @@ public class MergeNode : RenderNode
 
     private void Merge(DrawingSurface target, RenderContext context)
     {
-        //TODO: Obsereve if behavior is correct, it could be that some background rendered elements influence Top with different blend mode.
         if (Bottom.Value != null && Top.Value != null)
         {
+            int saved = target.Canvas.SaveLayer();
             Bottom.Value.Paint(context, target);
 
             paint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
-            int saved = target.Canvas.SaveLayer(paint);
+            target.Canvas.SaveLayer(paint);
             
             Top.Value.Paint(context, target);
             target.Canvas.RestoreToCount(saved);

+ 8 - 30
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageLeftNode.cs

@@ -17,56 +17,34 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 [PairNode(typeof(ModifyImageRightNode), "ModifyImageZone", true)]
 public class ModifyImageLeftNode : Node, IPairNode
 {
-    public InputProperty<Texture?> Image { get; }
+    public RenderInputProperty Image { get; }
 
     public FuncOutputProperty<Float2> Coordinate { get; }
 
     public FuncOutputProperty<Half4> Color { get; }
 
     public Guid OtherNode { get; set; }
-
-    private ConcurrentDictionary<RenderContext, Pixmap> pixmapCache = new();
+    
+    public Texture InputTexture { get; private set; }
 
     public ModifyImageLeftNode()
     {
-        Image = CreateInput<Texture>("Surface", "IMAGE", null);
+        Image = CreateRenderInput("Surface", "IMAGE");
         Coordinate = CreateFuncOutput("Coordinate", "UV", ctx => ctx.OriginalPosition);
         Color = CreateFuncOutput("Color", "COLOR", GetColor);
     }
-
+    
     private Half4 GetColor(FuncContext context)
     {
         context.ThrowOnMissingContext();
 
-        return context.SampleTexture(Image.Value, context.SamplePosition);
-
-        /*var targetPixmap = pixmapCache[context.RenderingContext];
-
-        if (targetPixmap == null)
-            return new Color();
-
-        var x = context.Position.X * context.Size.X;
-        var y = context.Position.Y * context.Size.Y;
-
-        return targetPixmap.GetPixelColor((int)x, (int)y);*/
-    }
-
-    internal void PreparePixmap(RenderContext forContext)
-    {
-        pixmapCache[forContext] = Image.Value?.PeekReadOnlyPixels();
-    }
-
-    internal void DisposePixmap(RenderContext forContext)
-    {
-        if (pixmapCache.TryRemove(forContext, out var targetPixmap))
-        {
-            targetPixmap?.Dispose();
-        }
+        return context.SampleSurface(InputTexture.DrawingSurface, context.SamplePosition);
     }
 
     protected override void OnExecute(RenderContext context)
     {
-        //return Image.Value;
+        InputTexture = RequestTexture(0, context.DocumentSize);
+        Image.Value.Paint(context, InputTexture.DrawingSurface);
     }
 
     public override Node CreateCopy() => new ModifyImageLeftNode();

+ 54 - 98
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageRightNode.cs

@@ -16,7 +16,7 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
 [NodeInfo("ModifyImageRight")]
 [PairNode(typeof(ModifyImageLeftNode), "ModifyImageZone")]
-public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
+public class ModifyImageRightNode : RenderNode, IPairNode, ICustomShaderNode
 {
     public Guid OtherNode { get; set; }
 
@@ -25,20 +25,17 @@ public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
     public FuncInputProperty<Float2> Coordinate { get; }
     public FuncInputProperty<Half4> Color { get; }
 
-    public OutputProperty<Texture> Output { get; }
-
 
     private string _lastSksl;
-    
+
 
     public ModifyImageRightNode()
     {
         Coordinate = CreateFuncInput(nameof(Coordinate), "UV", new Float2("coords"));
         Color = CreateFuncInput(nameof(Color), "COLOR", new Half4(""));
-        Output = CreateOutput<Texture>(nameof(Output), "OUTPUT", null);
     }
 
-    protected override void OnExecute(RenderContext renderContext)
+    protected override void OnPaint(RenderContext renderContext, DrawingSurface targetSurface)
     {
         if (OtherNode == null)
         {
@@ -49,13 +46,13 @@ public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
             }
         }
 
-        var startNode = FindStartNode(); 
+        var startNode = FindStartNode();
         if (startNode == null)
         {
             return;
         }
-        
-        if (startNode.Image.Value is not { Size: var size })
+
+        if (startNode.InputTexture is not { Size: var size })
         {
             return;
         }
@@ -65,108 +62,67 @@ public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
 
         Texture surface = RequestTexture(0, size);
 
-        if (!surface.IsHardwareAccelerated)
-        {
-            startNode.PreparePixmap(renderContext);
-
-            using Pixmap targetPixmap = surface.PeekReadOnlyPixels();
-
-            ModifyImageInParallel(renderContext, targetPixmap, width, height);
+        ShaderBuilder builder = new(size);
+        FuncContext context = new(renderContext, builder);
 
-            startNode.DisposePixmap(renderContext);
-        }
-        else
+        if (Coordinate.Connection != null)
         {
-            ShaderBuilder builder = new(size);
-            FuncContext context = new(renderContext, builder);
-
-            if (Coordinate.Connection != null)
+            var coordinate = Coordinate.Value(context);
+            if (string.IsNullOrEmpty(coordinate.VariableName))
             {
-                var coordinate = Coordinate.Value(context);
-                if (string.IsNullOrEmpty(coordinate.VariableName))
-                {
-                    builder.SetConstant(context.SamplePosition, coordinate);
-                }
-                else
-                {
-                    builder.Set(context.SamplePosition, coordinate);
-                }
+                builder.SetConstant(context.SamplePosition, coordinate);
             }
             else
             {
-                var constCoords = Coordinate.NonOverridenValue(FuncContext.NoContext);
-                constCoords.VariableName = "constCords";
-                builder.AddUniform(constCoords.VariableName, constCoords.ConstantValue);
-                builder.Set(context.SamplePosition, constCoords);
-            }
-
-            if (Color.Connection != null)
-            {
-                builder.ReturnVar(Color.Value(context));
+                builder.Set(context.SamplePosition, coordinate);
             }
-            else
-            {
-                Half4 color = Color.NonOverridenValue(FuncContext.NoContext);
-                color.VariableName = "color";
-                builder.AddUniform(color.VariableName, color.ConstantValue);
-                builder.ReturnVar(color);
-            }
-
-            string sksl = builder.ToSkSl();
-            if (sksl != _lastSksl)
-            {
-                _lastSksl = sksl;
-                drawingPaint?.Shader?.Dispose();
-                drawingPaint.Shader = builder.BuildShader();
-            }
-            else
-            {
-                drawingPaint.Shader = drawingPaint.Shader.WithUpdatedUniforms(builder.Uniforms);
-            }
-
-            surface.DrawingSurface.Canvas.DrawPaint(drawingPaint);
-            builder.Dispose();
         }
-        
-        Output.Value = surface;
-    }
+        else
+        {
+            var constCoords = Coordinate.NonOverridenValue(FuncContext.NoContext);
+            constCoords.VariableName = "constCords";
+            builder.AddUniform(constCoords.VariableName, constCoords.ConstantValue);
+            builder.Set(context.SamplePosition, constCoords);
+        }
 
-    private unsafe void ModifyImageInParallel(RenderContext renderContext, Pixmap targetPixmap, int width,
-        int height)
-    {
-        int threads = Environment.ProcessorCount;
-        int chunkHeight = height / threads;
+        if (Color.Connection != null)
+        {
+            builder.ReturnVar(Color.Value(context));
+        }
+        else
+        {
+            Half4 color = Color.NonOverridenValue(FuncContext.NoContext);
+            color.VariableName = "color";
+            builder.AddUniform(color.VariableName, color.ConstantValue);
+            builder.ReturnVar(color);
+        }
 
-        /*Parallel.For(0, threads, i =>
+        string sksl = builder.ToSkSl();
+        if (sksl != _lastSksl)
+        {
+            _lastSksl = sksl;
+            drawingPaint?.Shader?.Dispose();
+            drawingPaint.Shader = builder.BuildShader();
+        }
+        else
         {
-            FuncContext context = new(renderingContext);
+            drawingPaint.Shader = drawingPaint.Shader.WithUpdatedUniforms(builder.Uniforms);
+        }
 
-            int startY = i * chunkHeight;
-            int endY = (i + 1) * chunkHeight;
-            if (i == threads - 1)
-            {
-                endY = height;
-            }
+        surface.DrawingSurface.Canvas.DrawPaint(drawingPaint);
 
-            Half* drawArray = (Half*)targetPixmap.GetPixels();
+        targetSurface.Canvas.DrawSurface(surface.DrawingSurface, 0, 0);
+        builder.Dispose();
+    }
 
-            for (int y = startY; y < endY; y++)
-            {
-                for (int x = 0; x < width; x++)
-                {
-                    context.UpdateContext(new VecD((double)x / width, (double)y / height), new VecI(width, height));
-                    var coordinate = Coordinate.Value(context);
-                    context.UpdateContext(coordinate, new VecI(width, height));
-
-                    var color = Color.Value(context);
-                    ulong colorBits = color.ToULong();
-
-                    int pixelOffset = (y * width + x) * 4;
-                    Half* drawPixel = drawArray + pixelOffset;
-                    *(ulong*)drawPixel = colorBits;
-                }
-            }
-        });*/
+    public override RectD? GetPreviewBounds(int frame, string elementToRenderName = "")
+    {
+        return null;
+    }
+
+    public override bool RenderPreview(DrawingSurface renderOn, ChunkResolution resolution, int frame, string elementToRenderName)
+    {
+        return false;
     }
 
     public override void Dispose()
@@ -189,7 +145,7 @@ public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
 
             return true;
         });
-        
+
         return startNode;
     }
 

+ 22 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Node.cs

@@ -37,7 +37,7 @@ public abstract class Node : IReadOnlyNode, IDisposable
         get => displayName;
         set => displayName = value;
     }
-    
+
     protected virtual bool ExecuteOnlyOnCacheChange => false;
 
     private bool _isDisposed;
@@ -57,7 +57,7 @@ public abstract class Node : IReadOnlyNode, IDisposable
         {
             return;
         }
-        
+
         OnExecute(context);
 
         if (ExecuteOnlyOnCacheChange)
@@ -202,6 +202,26 @@ public abstract class Node : IReadOnlyNode, IDisposable
         keyFrames.Add(value);
     }
 
+    protected RenderOutputProperty? CreateRenderOutput(string internalName, string displayName,
+        Func<Painter?>? nextInChain, Func<Painter?>? previous = null)
+    {
+        RenderOutputProperty prop = new RenderOutputProperty(this, internalName, displayName, null);
+        prop.FirstInChain = previous;
+        prop.NextInChain = nextInChain;
+        AddOutputProperty(prop);
+
+        return prop;
+    }
+
+    protected RenderInputProperty CreateRenderInput(string internalName, string displayName)
+    {
+        RenderInputProperty prop = new RenderInputProperty(this, internalName, displayName, null);
+        AddInputProperty(prop);
+
+        return prop;
+    }
+
+
     protected FuncInputProperty<T> CreateFuncInput<T>(string propName, string displayName, T defaultValue)
     {
         var property = new FuncInputProperty<T>(this, propName, displayName, defaultValue);

+ 5 - 24
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/RenderNode.cs

@@ -5,15 +5,15 @@ using PixiEditor.Numerics;
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
-public abstract class RenderNode : Node, IPreviewRenderable 
+public abstract class RenderNode : Node, IPreviewRenderable
 {
     public RenderOutputProperty Output { get; }
 
     public RenderNode()
     {
         Painter painter = new Painter(OnPaint);
-        Output = CreateRenderOutput("Output", "OUTPUT", 
-            () => painter, 
+        Output = CreateRenderOutput("Output", "OUTPUT",
+            () => painter,
             () => this is IRenderInput renderInput ? renderInput.Background.Value : null);
     }
 
@@ -25,32 +25,13 @@ public abstract class RenderNode : Node, IPreviewRenderable
             {
                 output.ChainToPainterValue();
             }
-        } 
+        }
     }
-    
-    protected abstract void OnPaint(RenderContext context, DrawingSurface surface);
-    
-    protected RenderOutputProperty? CreateRenderOutput(string internalName, string displayName, Func<Painter?>? nextInChain, Func<Painter?>? previous = null)
-    {
-        RenderOutputProperty prop = new RenderOutputProperty(this, internalName, displayName, null);
-        prop.FirstInChain = previous;
-        prop.NextInChain = nextInChain;
-        AddOutputProperty(prop);
 
-        return prop;
-    }
-
-    protected RenderInputProperty CreateRenderInput(string internalName, string displayName)
-    {
-        RenderInputProperty prop = new RenderInputProperty(this, internalName, displayName, null);
-        AddInputProperty(prop);
-
-        return prop;
-    }
+    protected abstract void OnPaint(RenderContext context, DrawingSurface surface);
 
     public abstract RectD? GetPreviewBounds(int frame, string elementToRenderName = "");
 
     public abstract bool RenderPreview(DrawingSurface renderOn, ChunkResolution resolution, int frame,
         string elementToRenderName);
-
 }

+ 3 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/SampleImageNode.cs

@@ -28,14 +28,15 @@ public class SampleImageNode : Node
     {
         context.ThrowOnMissingContext();
 
-        if (Image.Value is null)
+        /*if (Image.Value is null)
         {
             return new Half4("");
         }
 
         Float2 uv = context.GetValue(Coordinate);
 
-        return context.SampleTexture(Image.Value, uv);
+        return context.SampleSurface(Image.Value, uv);*/
+        return new Half4("");// TODO: Implement this
     }
 
     protected override void OnExecute(RenderContext context)

+ 2 - 2
src/PixiEditor.DrawingApi.Core/Shaders/Generation/Expressions/TextureSampler.cs → src/PixiEditor.DrawingApi.Core/Shaders/Generation/Expressions/SurfaceSampler.cs

@@ -1,8 +1,8 @@
 namespace PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
 
-public class TextureSampler : ShaderExpressionVariable<Texture>
+public class SurfaceSampler : ShaderExpressionVariable<Texture>
 {
-    public TextureSampler(string name) : base(name)
+    public SurfaceSampler(string name) : base(name)
     {
     }
 

+ 13 - 7
src/PixiEditor.DrawingApi.Core/Shaders/Generation/ShaderBuilder.cs

@@ -4,6 +4,7 @@ using System.Linq;
 using System.Text;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
+using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.DrawingApi.Core.Shaders.Generation;
@@ -16,7 +17,7 @@ public class ShaderBuilder
 
     private List<ShaderExpressionVariable> _variables = new List<ShaderExpressionVariable>();
 
-    private Dictionary<Texture, TextureSampler> _samplers = new Dictionary<Texture, TextureSampler>();
+    private Dictionary<DrawingSurface, SurfaceSampler> _samplers = new Dictionary<DrawingSurface, SurfaceSampler>();
 
     public BuiltInFunctions Functions { get; } = new();
 
@@ -28,6 +29,11 @@ public class ShaderBuilder
     public Shader BuildShader()
     {
         string generatedSksl = ToSkSl();
+        /*string testSksl = """
+                          
+                          
+
+                          """;*/
         return new Shader(generatedSksl, Uniforms);
     }
 
@@ -56,23 +62,23 @@ public class ShaderBuilder
         }
     }
 
-    public TextureSampler AddOrGetTexture(Texture texture)
+    public SurfaceSampler AddOrGetSurface(DrawingSurface surface)
     {
-        if (_samplers.TryGetValue(texture, out var sampler))
+        if (_samplers.TryGetValue(surface, out var sampler))
         {
             return sampler;
         }
 
         string name = $"texture_{GetUniqueNameNumber()}";
-        using var snapshot = texture.DrawingSurface.Snapshot();
+        using var snapshot = surface.Snapshot();
         Uniforms[name] = new Uniform(name, snapshot.ToShader());
-        var newSampler = new TextureSampler(name);
-        _samplers[texture] = newSampler;
+        var newSampler = new SurfaceSampler(name);
+        _samplers[surface] = newSampler;
 
         return newSampler;
     }
 
-    public Half4 Sample(TextureSampler texName, Float2 pos)
+    public Half4 Sample(SurfaceSampler texName, Float2 pos)
     {
         string resultName = $"color_{GetUniqueNameNumber()}";
         Half4 result = new Half4(resultName);