From 756b1d2a9d91f644265b5f3a95e637257a84e95a Mon Sep 17 00:00:00 2001 From: Josef Date: Fri, 14 Feb 2025 08:44:20 +0100 Subject: [PATCH] Texture Combiner --- Runtime/Colors/ColorX.cs | 37 +++++++++++- .../TextureCombiner/TextureCombiner.cs | 17 ++++++ .../TextureCombinerBlendMode.cs | 53 +++++++++++++++++ .../TextureCombiner/TextureCombinerBuffer.cs | 57 +++++++++++++++++++ .../TextureCombiner/TextureCombinerLayer.cs | 27 +++++++++ .../TextureCombinerProcessingContext.cs | 17 ++++++ .../TextureCombinerProcessingRect.cs | 21 +++++++ 7 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 Runtime/Procedural/Textures/TextureCombiner/TextureCombiner.cs create mode 100644 Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBlendMode.cs create mode 100644 Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs create mode 100644 Runtime/Procedural/Textures/TextureCombiner/TextureCombinerLayer.cs create mode 100644 Runtime/Procedural/Textures/TextureCombiner/TextureCombinerProcessingContext.cs create mode 100644 Runtime/Procedural/Textures/TextureCombiner/TextureCombinerProcessingRect.cs diff --git a/Runtime/Colors/ColorX.cs b/Runtime/Colors/ColorX.cs index 8f4e0ef..7293e69 100644 --- a/Runtime/Colors/ColorX.cs +++ b/Runtime/Colors/ColorX.cs @@ -2,8 +2,37 @@ using Godot; namespace Rokojori { - public class ColorX + public static class ColorX { + public static float AlphaMultipliedR( this Color c ) + { + return c.R * c.A; + } + + public static float AlphaMultipliedG( this Color c ) + { + return c.G * c.A; + } + + public static float AlphaMultipliedB( this Color c ) + { + return c.B * c.A; + } + + public static Color Blend( Color bottom, Color top ) + { + var fade = ( 1f - top.A ); + var a0 = top.A + bottom.A * fade; + + var xR = top.AlphaMultipliedR() + bottom.AlphaMultipliedR() * fade; + var xG = top.AlphaMultipliedG() + bottom.AlphaMultipliedG() * fade; + var xB = top.AlphaMultipliedB() + bottom.AlphaMultipliedB() * fade; + + var normalizer = 1f / a0; + + return new Color( xR, xG, xB, 1 ) * normalizer; + } + public static Color Lerp( Color a, Color b, float amount ) { return a.Lerp( b, amount ); @@ -40,6 +69,12 @@ namespace Rokojori return color; } + public static Color FadeAlpha( this Color color, float fade ) + { + color.A = color.A * fade; + return color; + } + public static Color SetAlpha( Color color, float alpha ) { color.A = alpha; diff --git a/Runtime/Procedural/Textures/TextureCombiner/TextureCombiner.cs b/Runtime/Procedural/Textures/TextureCombiner/TextureCombiner.cs new file mode 100644 index 0000000..801108a --- /dev/null +++ b/Runtime/Procedural/Textures/TextureCombiner/TextureCombiner.cs @@ -0,0 +1,17 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class TextureCombiner:Resource + { + [Export] + public TextureCombinerLayer[] layers; + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBlendMode.cs b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBlendMode.cs new file mode 100644 index 0000000..8b65aa4 --- /dev/null +++ b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBlendMode.cs @@ -0,0 +1,53 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + public enum TextureCombinerBlendMode + { + Normal, + Add, + Multiply + } + + public class TextureCombinerBlendModeAlgorithm + { + public static void Blend( TextureCombinerBlendMode blendMode, int x, int y, int w, int h, float topOpacity, + TextureBuffer bottom, TextureBuffer top, TextureBuffer output + ) + { + if ( TextureCombinerBlendMode.Normal == blendMode ) + { + BlendNormal( x, y, w, h, topOpacity, bottom, top, output ); + } + } + + static void BlendNormal( int x, int y, int w, int h, float topOpacity, + TextureBuffer bottom, TextureBuffer top, TextureBuffer output ) + { + for ( int i = 0; i < w; i++ ) + { + var rx = x + i; + + for ( int j = 0; j < h; j++ ) + { + var ry = y + j; + + var index = output.ComputeIndexFromPosition( rx, ry ); + + var topColor = top.GetIndexed( index ).FadeAlpha( topOpacity ); + var bottomColor = bottom.GetIndexed( index ); + + var outputColor = bottomColor.Blend( topColor ); + + output.SetIndexed( index, outputColor ); + + } + } + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs new file mode 100644 index 0000000..99ac6dd --- /dev/null +++ b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs @@ -0,0 +1,57 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + public class TextureBuffer + { + int _width; + public int width => _width; + + int _height; + public int height => _height; + + T[] _pixels; + + public static TextureBuffer Create( int w, int h ) + { + var tb = new TextureBuffer(); + tb._height = h; + tb._width = w; + tb._pixels = new T[ w * h ]; + + return tb; + } + + public int ComputeIndexFromPosition( int x, int y ) + { + return x + y * _width; + } + + public void SetAt( int x, int y, T value ) + { + SetIndexed( ComputeIndexFromPosition( x, y ), value ); + } + + public void SetIndexed( int index, T value ) + { + _pixels[ index ] = value; + } + + public T GetAt( int x, int y ) + { + return GetIndexed( ComputeIndexFromPosition( x, y ) ); + } + + public T GetIndexed( int index ) + { + return _pixels[ index ]; + } + + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerLayer.cs b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerLayer.cs new file mode 100644 index 0000000..99ae94d --- /dev/null +++ b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerLayer.cs @@ -0,0 +1,27 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; +using System.Threading; +using System.Threading.Tasks; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class TextureCombinerLayer:Resource + { + [Export] + public TextureCombinerBlendMode blendMode; + + [Export( PropertyHint.Range, "0,1")] + public float opacity = 1; + + public async Task Process( TextureCombinerProcessingRect processingRect ) + { + return; + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerProcessingContext.cs b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerProcessingContext.cs new file mode 100644 index 0000000..bd004a8 --- /dev/null +++ b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerProcessingContext.cs @@ -0,0 +1,17 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + public class TextureCombinerContext + { + public TextureCombiner combiner; + public int imageWidth = 0; + public int imageHeight = 0; + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerProcessingRect.cs b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerProcessingRect.cs new file mode 100644 index 0000000..2095eae --- /dev/null +++ b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerProcessingRect.cs @@ -0,0 +1,21 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; + + + +namespace Rokojori +{ + public class TextureCombinerProcessingRect + { + public TextureCombinerContext context; + public int processingX = 0; + public int processingY = 0; + public int processingWidht = 0; + public int processingHeight = 0; + + public TextureBuffer output; + + } +} \ No newline at end of file