Browse Source

Conection fixes and some nodes converted

flabbet 1 year ago
parent
commit
5f232eaedf

+ 7 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Context/FuncContext.cs

@@ -41,7 +41,7 @@ public class FuncContext
         Position = new Float2("coords"); // input argument 'half4 main(float2 coords)'
     }
 
-    public Half4 SampleTexture(Texture? imageValue, Float2 pos)
+    public Half4 SampleTexture(Texture imageValue, Float2 pos)
     {
         TextureSampler texName = Builder.AddOrGetTexture(imageValue);
         return Builder.Sample(texName, pos);
@@ -68,6 +68,12 @@ public class FuncContext
         return Builder.ConstructHalf4(r, g, b, a);
     }
 
+
+    public Half4 NewHalf4(Expression assignment)
+    {
+        return Builder.AssignNewHalf4(assignment);
+    }
+
     public Float1 GetValue(FuncInputProperty<Float1> getFrom)
     {
         if (getFrom.Connection == null || !IsFuncType(getFrom))

+ 5 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/EmptyImageNode.cs

@@ -27,6 +27,11 @@ public class CreateImageNode : Node
 
     protected override Texture? OnExecute(RenderingContext context)
     {
+        if (Size.Value.X <= 0 || Size.Value.Y <= 0)
+        {
+            return null;
+        }
+        
         var surface = new Texture(Size.Value);
 
         _paint.Color = Fill.Value;

+ 5 - 3
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ImageLayerNode.cs

@@ -197,17 +197,20 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         {
             tempSizeInChunks.Y++;
         }
+        
+        VecI tempSize = tempSizeInChunks * context.ChunkResolution.PixelSize();
+        tempSize = new VecI(Math.Min(tempSize.X, workingSurface.Size.X), Math.Min(tempSize.Y, workingSurface.Size.Y));
 
         if (shouldClear)
         {
             workingSurface.DrawingSurface.Canvas.DrawRect(
                 new RectI(
                     VecI.Zero,
-                    tempSizeInChunks * context.ChunkResolution.PixelSize()),
+                    tempSize), 
                 clearPaint);
         }
         
-        using Texture tempSurface = new Texture(tempSizeInChunks * context.ChunkResolution.PixelSize());
+        using Texture tempSurface = new Texture(tempSize);
 
         if (requiresTopLeft)
         {
@@ -252,7 +255,6 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         DrawChunk(frameImage, context, tempSurface, new VecI(0, 0));
         
         blendPaint.SetFilters(Filters.Value);
-        var destinationRect = CalculateDestinationRect(context);
         workingSurface.DrawingSurface.Canvas.DrawSurface(tempSurface.DrawingSurface, VecI.Zero, blendPaint);
     }
 

+ 11 - 10
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/LerpColorNode.cs

@@ -2,6 +2,7 @@
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
+using PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
@@ -9,29 +10,29 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 [NodeInfo("Lerp")]
 public class LerpColorNode : Node // TODO: ILerpable as inputs? 
 {
-    public FuncOutputProperty<Color> Result { get; } 
-    public FuncInputProperty<Color> From { get; }
-    public FuncInputProperty<Color> To { get; }
-    public FuncInputProperty<double> Time { get; }
+    public FuncOutputProperty<Half4> Result { get; } 
+    public FuncInputProperty<Half4> From { get; }
+    public FuncInputProperty<Half4> To { get; }
+    public FuncInputProperty<Float1> Time { get; }
     
     public override string DisplayName { get; set; } = "LERP_NODE";
     
     
     public LerpColorNode()
     {
-        Result = CreateFuncOutput("Result", "RESULT", Lerp);
-        From = CreateFuncInput("From", "FROM", Colors.Black);
-        To = CreateFuncInput("To", "TO", Colors.White);
-        Time = CreateFuncInput("Time", "TIME", 0.5);
+        Result = CreateFuncOutput<Half4>("Result", "RESULT", Lerp);
+        From = CreateFuncInput<Half4>("From", "FROM", Colors.Black);
+        To = CreateFuncInput<Half4>("To", "TO", Colors.White);
+        Time = CreateFuncInput<Float1>("Time", "TIME", 0.5);
     }
 
-    private Color Lerp(FuncContext arg)
+    private Half4 Lerp(FuncContext arg)
     {
         var from = From.Value(arg);
         var to = To.Value(arg);
         var time = Time.Value(arg);
         
-        return Color.Lerp(from, to, time); 
+        return arg.NewHalf4(ShaderMath.Lerp(from, to, time)); 
     }
 
     protected override Texture? OnExecute(RenderingContext context)

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

@@ -79,7 +79,7 @@ public abstract class Node : IReadOnlyNode, IDisposable
         {
             throw new ObjectDisposedException("Texture was disposed after execution.");
         }
-
+        
         UpdateCache(context);
         return CachedResult;
     }

+ 11 - 20
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/SampleImageNode.cs

@@ -2,6 +2,7 @@
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
+using PixiEditor.DrawingApi.Core.Shaders.Generation.Expressions;
 using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.Numerics;
 
@@ -10,45 +11,35 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 [NodeInfo("SampleImage")]
 public class SampleImageNode : Node
 {
-    private Pixmap? pixmap;
-
     public InputProperty<Texture?> Image { get; }
 
-    public FuncOutputProperty<VecD> Coordinate { get; }
+    public FuncOutputProperty<Float2> Coordinate { get; }
 
-    public FuncOutputProperty<Color> Color { get; }
+    public FuncOutputProperty<Half4> Color { get; }
 
     public override string DisplayName { get; set; } = "SAMPLE_IMAGE";
 
     public SampleImageNode()
     {
         Image = CreateInput<Texture>(nameof(Texture), "IMAGE", null);
-        //TODO: Implement this
-        //Coordinate = CreateFuncOutput(nameof(Coordinate), "UV", ctx => ctx.Position);
-        //Color = CreateFuncOutput(nameof(Color), "COLOR", GetColor);
+        Coordinate = CreateFuncOutput(nameof(Coordinate), "UV", ctx => ctx.Position);
+        Color = CreateFuncOutput(nameof(Color), "COLOR", GetColor);
     }
 
-    /*private Color GetColor(FuncContext context)
+    private Half4 GetColor(FuncContext context)
     {
         context.ThrowOnMissingContext();
 
-        if (pixmap == null)
-            return new Color();
-
-        var x = context.Position.X * context.Size.X;
-        var y = context.Position.Y * context.Size.Y;
+        if (Image.Value is null)
+        {
+            return new Half4("");
+        }
 
-        return pixmap.GetPixelColor((int)x, (int)y);
-    }*/
-
-    internal void PreparePixmap()
-    {
-        pixmap = Image.Value?.PeekReadOnlyPixels();
+        return context.SampleTexture(Image.Value, context.Position);
     }
 
     protected override Texture? OnExecute(RenderingContext context)
     {
-        PreparePixmap();
         return Image.Value;
     }
 

+ 4 - 4
src/PixiEditor.DrawingApi.Core/Shaders/Generation/Expressions/Half4.cs

@@ -6,10 +6,10 @@ public class Half4(string name) : ShaderExpressionVariable<Color>(name)
 {
     public override string ConstantValueString => $"half4({ConstantValue.R}, {ConstantValue.G}, {ConstantValue.B}, {ConstantValue.A})";
     
-    public Float1 R => new Float1($"{VariableName}.r") { ConstantValue = ConstantValue.R };
-    public Float1 G => new Float1($"{VariableName}.g") { ConstantValue = ConstantValue.G };
-    public Float1 B => new Float1($"{VariableName}.b") { ConstantValue = ConstantValue.B };
-    public Float1 A => new Float1($"{VariableName}.a") { ConstantValue = ConstantValue.A };
+    public Float1 R => new Float1(string.IsNullOrEmpty(VariableName) ? string.Empty : $"{VariableName}.r") { ConstantValue = ConstantValue.R };
+    public Float1 G => new Float1(string.IsNullOrEmpty(VariableName) ? string.Empty : $"{VariableName}.g") { ConstantValue = ConstantValue.G };
+    public Float1 B => new Float1(string.IsNullOrEmpty(VariableName) ? string.Empty : $"{VariableName}.b") { ConstantValue = ConstantValue.B };
+    public Float1 A => new Float1(string.IsNullOrEmpty(VariableName) ? string.Empty : $"{VariableName}.a") { ConstantValue = ConstantValue.A };
     
     public static implicit operator Half4(Color value) => new Half4("") { ConstantValue = value };
     public static explicit operator Color(Half4 value) => value.ConstantValue;

+ 5 - 0
src/PixiEditor.DrawingApi.Core/Shaders/Generation/Expressions/ShaderMath.cs

@@ -43,4 +43,9 @@ public static class ShaderMath
     {
         return new Expression($"tan({x.ExpressionValue})");
     }
+    
+    public static Expression Lerp(ShaderExpressionVariable a, ShaderExpressionVariable b, ShaderExpressionVariable t)
+    {
+        return new Expression($"mix({a.VarOrConst()}, {b.VarOrConst()}, {t.VarOrConst()})"); 
+    }
 }

+ 11 - 0
src/PixiEditor.DrawingApi.Core/Shaders/Generation/ShaderBuilder.cs

@@ -158,6 +158,17 @@ public class ShaderBuilder
         return result;
     }
 
+
+    public Half4 AssignNewHalf4(Expression assignment)
+    {
+        string name = $"color_{GetUniqueNameNumber()}";
+        Half4 result = new Half4(name);
+        _variables.Add(result);
+
+        _bodyBuilder.AppendLine($"half4 {name} = {assignment.ExpressionValue};");
+        return result;
+    }
+
     public void Dispose()
     {
         _bodyBuilder.Clear();

+ 7 - 0
src/PixiEditor.DrawingApi.Core/Shaders/Generation/ShaderExpressionVariable.cs

@@ -21,6 +21,8 @@ public abstract class ShaderExpressionVariable(string name) : Expression
     {
         return string.IsNullOrEmpty(VariableName) ? ConstantValueString : VariableName;
     }
+
+    public abstract object GetConstant();
 }
 
 public abstract class ShaderExpressionVariable<TConstant>(string name)
@@ -47,4 +49,9 @@ public abstract class ShaderExpressionVariable<TConstant>(string name)
             }
         }
     }
+    
+    public override object GetConstant()
+    {
+        return ConstantValue;
+    }
 }

+ 1 - 0
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaShaderImplementation.cs

@@ -107,6 +107,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
                 throw new InvalidOperationException("Shader is not a runtime effect shader");
             }
             
+            // TODO: Don't reupload shaders if they are the same
             SKRuntimeEffectUniforms effectUniforms = UniformsToSkUniforms(uniforms, effect);
             SKRuntimeEffectChildren effectChildren = UniformsToSkChildren(uniforms, effect);
             

+ 6 - 1
src/PixiEditor/Helpers/SerializationUtil.cs

@@ -1,5 +1,6 @@
 using System.Collections;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Context;
+using PixiEditor.DrawingApi.Core.Shaders.Generation;
 using PixiEditor.Models.Serialization;
 using PixiEditor.Models.Serialization.Factories;
 
@@ -14,10 +15,14 @@ public static class SerializationUtil
         {
             return null;
         }
-
+        
         if (value is Delegate del)
         {
             value = del.DynamicInvoke(FuncContext.NoContext);
+            if (value is ShaderExpressionVariable expressionVariable)
+            { 
+                value = expressionVariable.GetConstant();
+            }
         }
 
         var factory = allFactories.FirstOrDefault(x => x.OriginalType == value.GetType());