From 7b68cc7f1f027f6a78164e5be2f36079e4ba9e2f Mon Sep 17 00:00:00 2001 From: Josef Date: Wed, 30 Apr 2025 22:18:22 +0200 Subject: [PATCH] JFA Texture Dilation Working --- Runtime/Colors/ColorX.cs | 21 ++ Runtime/Logging/RJLog.cs | 7 +- Runtime/Procedural/Baking/GrabTexture2.cs | 55 ++++-- .../Baking/MultiBaker/MultiBaker.cs | 16 +- Runtime/Procedural/Baking/TextureDilate.cs | 184 ++++++++++++++++++ .../Procedural/Baking/TextureDilate.cs.uid | 1 + Runtime/Procedural/Baking/TextureMerger.cs | 1 + .../TextureCombiner/TextureCombinerBuffer.cs | 33 +++- .../BoxBlur/BoxBlurEffect.cs | 134 +++++++++++++ .../BoxBlur/BoxBlurEffect.cs.uid | 1 + .../Rendering/Context/RDContext.Messages.cs | 8 +- Runtime/Rendering/Context/RDContext.cs | 16 +- Runtime/Rendering/Objects/RDPushConstants.cs | 8 +- Runtime/Rendering/Objects/RDTexture.cs | 1 + .../Processors/Blurs/BoxBlur/BoxBlur.glsl | 99 ++++++++++ .../Blurs/BoxBlur/BoxBlur.glsl.import | 14 ++ .../Processors/Blurs/BoxBlur/RG_BoxBlur.cs | 17 ++ .../Blurs/BoxBlur/RG_BoxBlur.cs.uid | 1 + .../Nodes/Processors/Copy/Copy.glsl | 6 +- .../Processors/Generic/CEG_BufferTexture.cs | 4 +- .../Processors/Generic/CEG_ImageProcessor.cs | 8 + .../Nodes/Processors/JFA/CEG_JFAAssign.cs.uid | 1 + .../Nodes/Processors/JFA/JFA_Assign.glsl | 20 +- .../Nodes/Processors/JFA/JFA_Initialize.glsl | 2 + .../Nodes/Processors/JFA/JFA_Iterate.glsl | 6 +- .../Nodes/Processors/Logic/RG_SwapRepeat.cs | 96 +++++++++ .../Processors/Logic/RG_SwapRepeat.cs.uid | 1 + Runtime/Rendering/RenderGraph/RDGraph.cs | 8 +- .../RenderGraph/RDGraphTextureSlot.cs | 12 +- .../RenderGraph/RDShaderProcessor.cs | 49 ++++- 30 files changed, 762 insertions(+), 68 deletions(-) create mode 100644 Runtime/Procedural/Baking/TextureDilate.cs create mode 100644 Runtime/Procedural/Baking/TextureDilate.cs.uid create mode 100644 Runtime/Rendering/Compositor/CompositorEffects/BoxBlur/BoxBlurEffect.cs create mode 100644 Runtime/Rendering/Compositor/CompositorEffects/BoxBlur/BoxBlurEffect.cs.uid create mode 100644 Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl create mode 100644 Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl.import create mode 100644 Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/RG_BoxBlur.cs create mode 100644 Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/RG_BoxBlur.cs.uid create mode 100644 Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/CEG_JFAAssign.cs.uid create mode 100644 Runtime/Rendering/RenderGraph/Nodes/Processors/Logic/RG_SwapRepeat.cs create mode 100644 Runtime/Rendering/RenderGraph/Nodes/Processors/Logic/RG_SwapRepeat.cs.uid diff --git a/Runtime/Colors/ColorX.cs b/Runtime/Colors/ColorX.cs index 27a80e6..261964a 100644 --- a/Runtime/Colors/ColorX.cs +++ b/Runtime/Colors/ColorX.cs @@ -42,6 +42,27 @@ namespace Rokojori return MathX.Clamp01( f ); } + public static Color Gamma( this Color color, float gamma ) + { + return new Color( + Mathf.Pow( color.R, gamma ), + Mathf.Pow( color.G, gamma ), + Mathf.Pow( color.B, gamma ), + color.A + ); + } + + public static Color linearToSRGB( this Color color ) + { + return color.Gamma( 1.0f / 2.2f ); + } + + public static Color srgbToLinear( this Color color ) + { + return color.Gamma( 2.2f ); + } + + public static Color Blend( Color bottom, Color top ) { var fade = ( 1f - top.A ); diff --git a/Runtime/Logging/RJLog.cs b/Runtime/Logging/RJLog.cs index 55d3db4..caecd65 100644 --- a/Runtime/Logging/RJLog.cs +++ b/Runtime/Logging/RJLog.cs @@ -210,6 +210,11 @@ namespace Rokojori LogMessage( GetLogString( objects ) ); } + public static void LogWithTraceOffset( int offset, params object[] objects ) + { + LogMessage( GetLogString( objects ), 3 + offset ); + } + public static void Log( Node node, params object[] objects) { LogMessage( "[color=#55aaff]" + HierarchyName.Of( node ) + "[/color]\n" + GetLogString( objects ), 4 ); @@ -225,7 +230,7 @@ namespace Rokojori LogErrorMessage( GetLogString( objects ) ); } - public static void ErrorFull( params object[] objects) + public static void ErrorWithFullTrace( params object[] objects) { LogErrorWithFullTrace( GetLogString( objects ) ); } diff --git a/Runtime/Procedural/Baking/GrabTexture2.cs b/Runtime/Procedural/Baking/GrabTexture2.cs index b155425..57830c6 100644 --- a/Runtime/Procedural/Baking/GrabTexture2.cs +++ b/Runtime/Procedural/Baking/GrabTexture2.cs @@ -21,6 +21,21 @@ namespace Rokojori [Export] public MeshInstance3D meshInstance3D; + [Export( PropertyHint.Range, "0,1" ) ] + public float intensity; + + [Export( PropertyHint.Range, "0,100" ) ] + public float noise; + + [Export( PropertyHint.Range, "1,100" ) ] + public float kernelOffset; + + [Export( PropertyHint.Range, "1,50" ) ] + public float kernelRadius; + + + + [ExportToolButton( "Grab Texture")] public Callable GrabButton => Callable.From( @@ -41,9 +56,6 @@ namespace Rokojori viewport.RenderTargetUpdateMode = updateMode; } - - - var viewPortFormat = RDTextureFormats.GetDataFormat( viewport ); var viewPortData = viewport.GetTexture().GetImage().GetData(); var viewPortSize = viewport.Size; @@ -63,23 +75,27 @@ namespace Rokojori var inputTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); inputTexture.SetData( viewPortData ); + this.LogInfo( "Creating graph" ); + var graph = CreateGraph( ctx, inputTexture, outputTexture ); + this.LogInfo( "Process graph" ); graph.ProcessForView(); ctx.SubmitAndSync(); - var width = outputTexture.width; - var height = outputTexture.height; - var format = outputTexture.imageFormat; + var width = inputTexture.width; + var height = inputTexture.height; + var format = inputTexture.imageFormat; - var data = outputTexture.GetData(); + var data = inputTexture.GetData(); - this.LogInfo( "Copying texture" ); - ctx.SubmitAndSync(); await this.RequestNextFrame(); + + this.LogInfo( "Copying texture" ); + var image = Image.CreateFromData( width, height, false, format, data ); var buffer = TextureCombinerBuffer.From( ImageTexture.CreateFromImage( image ) ); @@ -92,9 +108,6 @@ namespace Rokojori await this.RequestNextFrame(); - - - } @@ -106,27 +119,27 @@ namespace Rokojori var bufferTexture = CEG_BufferTexture.From( graph, ot ); var copy = new CEG_Copy( graph ); - var radialBlur = new CEG_RadialBlur( graph ); + var blur = new RD_BoxBlur( graph ); graph.InitializeNodes(); copy.SetTextureSlotInputs( viewTexture, bufferTexture ); - radialBlur.SetTextureSlotInputs( copy.output, copy.input ); + blur.SetTextureSlotInputs( copy.output, copy.input ); graph.SetProcessOrder( viewTexture, bufferTexture, - copy, radialBlur + copy, blur ); - radialBlur.constants.Set( - new Vector2( 0.5f, 0.5f ), - 0.5f, - 0.5f, - 16, - Vector2.Zero + blur.constants.Set( + intensity, + noise, + kernelOffset, + kernelRadius ); + ctx.Verbose( "Radial Blur constants:", blur.constants.size ); return graph; } diff --git a/Runtime/Procedural/Baking/MultiBaker/MultiBaker.cs b/Runtime/Procedural/Baking/MultiBaker/MultiBaker.cs index 716958d..62cc5be 100644 --- a/Runtime/Procedural/Baking/MultiBaker/MultiBaker.cs +++ b/Runtime/Procedural/Baking/MultiBaker/MultiBaker.cs @@ -137,6 +137,9 @@ namespace Rokojori [Export] public TextureMerger X_textureMerger; + [Export] + public TextureDilate X_textureDilate; + [Export] public SetBakingMaterials X_setBakingMaterials; @@ -159,6 +162,7 @@ namespace Rokojori public Texture2D X_bakedTextureDepth; + [Export] public bool X_baking = false; @@ -196,6 +200,9 @@ namespace Rokojori X_textureMerger.dilationRadius = dilationRadius; X_textureMerger.Initialize(); + X_textureDilate = this.CreateChild( "Texture Dilate" ); + X_textureDilate.viewport = X_textureMerger.X_textureMergerViewport; + X_outputMesh = this.CreateChild( "Output Mesh" ); X_texturePreview = this.CreateChild( "Texture Preview" ); @@ -303,13 +310,14 @@ namespace Rokojori await this.RequestNextFrame(); - Texture2D texture = X_textureMerger.X_textureMergerViewport.GetTexture(); + // Texture2D texture = X_textureMerger.X_textureMergerViewport.GetTexture(); - this.LogInfo( "Texture created:", bakingMaterialModes[ i ] ); + // this.LogInfo( "Texture created:", bakingMaterialModes[ i ] ); - await this.RequestNextFrame(); + // await this.RequestNextFrame(); - texture = await CPUTextureDilater.Dilate( texture, this.RequestNextFrame ); + X_textureDilate.viewport = X_textureMerger.X_textureMergerViewport; + Texture2D texture = await X_textureDilate.Grab(); this.LogInfo( "Assigning Texture", bakingMaterialModes[ i ] ); diff --git a/Runtime/Procedural/Baking/TextureDilate.cs b/Runtime/Procedural/Baking/TextureDilate.cs new file mode 100644 index 0000000..ff2a0cb --- /dev/null +++ b/Runtime/Procedural/Baking/TextureDilate.cs @@ -0,0 +1,184 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; +using System.Linq; +using System.Threading.Tasks; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class TextureDilate:SequenceAction + { + [Export] + public SubViewport viewport; + + [Export] + public Texture2D target; + + [Export( PropertyHint.Range, "0,15" ) ] + public int steps = 0; + + [ExportToolButton( "Grab Texture")] + public Callable GrabButton => Callable.From( + () => + { + Grab(); + } + ); + + public async Task Grab() + { + var updateMode = viewport.RenderTargetUpdateMode; + + if ( updateMode != SubViewport.UpdateMode.Always ) + { + viewport.RenderTargetUpdateMode = SubViewport.UpdateMode.Always; + await this.RequestNextFrame(); + viewport.RenderTargetUpdateMode = updateMode; + } + + var viewPortFormat = RDTextureFormats.GetDataFormat( viewport ); + var viewPortData = viewport.GetTexture().GetImage().GetData(); + var viewPortSize = viewport.Size; + + this.LogInfo( "Grabbed viewport context", viewPortFormat, viewPortSize ); + + this.LogInfo( "Creating context" ); + var ctx = RDContext.Local(); + ctx.computeSize = viewPortSize; + ctx.messageLogLevel = Messages.GetLevel( MessageType.Verbose ); + + + this.LogInfo( "Creating textures" ); + + var bufferTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); + var bufferTexture2 = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); + var resultTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); + var initTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); + + + var inputTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); + inputTexture.SetData( viewPortData ); + + this.LogInfo( "Creating graph" ); + + var graph = CreateGraph( ctx, inputTexture, initTexture, bufferTexture, bufferTexture2, resultTexture ); + + this.LogInfo( "Process graph" ); + graph.ProcessForView(); + + ctx.SubmitAndSync(); + + var exportTexture = resultTexture; + var width = exportTexture.width; + var height = exportTexture.height; + var format = exportTexture.imageFormat; + + var data = exportTexture.GetData(); + + ctx.SubmitAndSync(); + await this.RequestNextFrame(); + + + this.LogInfo( "Copying texture:", format ); + + var image = Image.CreateFromData( width, height, false, format, data ); + + var gammaConversion = 0; + + if ( RenderingDevice.DataFormat.R16G16B16A16Sfloat == viewPortFormat ) + { + gammaConversion = -1; + } + + var buffer = TextureCombinerBuffer.From( ImageTexture.CreateFromImage( image ), gammaConversion ); + var texture = buffer.CreateImageTexture(); + + + + target = texture; + + ctx.CleanUp(); + + return texture; + + } + + RDGraph CreateGraph( RDContext ctx, RDTexture it, RDTexture ii, RDTexture b1, RDTexture b2, RDTexture rt ) + { + var graph = new RDGraph( ctx ); + + var viewTexture = CEG_BufferTexture.From( graph, it ); + var initTexture = CEG_BufferTexture.From( graph, ii ); + var bufferTexture = CEG_BufferTexture.From( graph, b1 ); + var bufferTexture2 = CEG_BufferTexture.From( graph, b2 ); + var resultTexture = CEG_BufferTexture.From( graph, rt ); + + ctx.Verbose( "Init Texture:", initTexture.GetTexture() ); + + var jfaInititialize = new CEG_JFAInitialize( graph ); + jfaInititialize.constants.Set( 0.5f ); + + var copy = new CEG_Copy( graph ); + var jfaIterate = new CEG_JFAIterate( graph ); + var jfaAssign = new CEG_JFAAssign( graph ); + var repeat = new RG_SwapRepeat( graph ); + + var numSteps = steps == 0 ? + ( Mathf.RoundToInt( MathX.Exponent( 2, it.maxDimension ) ) - 1 ) : + steps; + + RJLog.Log( "Steps >>", numSteps, Mathf.Pow( 2, numSteps ) ); + + repeat.repeats = numSteps; + repeat.imageProcessor = jfaIterate; + + repeat.onPreProcess = + ( index ) => + { + var stepIndex = numSteps - ( index + 1 ); + var jump = Mathf.RoundToInt( Mathf.Pow( 2, stepIndex ) ); + + this.LogInfo( "Jump:", jump ); + jfaIterate.constants.Set( + jump + ); + }; + + + + graph.InitializeNodes(); + + + jfaInititialize.SetTextureSlotInputs( viewTexture, initTexture ); + copy.SetTextureSlotInputs( initTexture, bufferTexture ); + repeat.SetTextureSlotInputs( bufferTexture, bufferTexture2 ); + + var assignTexture = steps % 2 == 0 ? bufferTexture : bufferTexture2; + jfaAssign.SetTextureSlotInputs( assignTexture, resultTexture ); + jfaAssign.AddTextureSlotInput( viewTexture ); + + graph.SetProcessOrder( + viewTexture, + bufferTexture, + bufferTexture2, + initTexture, + resultTexture, + jfaInititialize, + copy, + repeat, + jfaAssign + ); + + + + return graph; + } + + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Baking/TextureDilate.cs.uid b/Runtime/Procedural/Baking/TextureDilate.cs.uid new file mode 100644 index 0000000..47228a4 --- /dev/null +++ b/Runtime/Procedural/Baking/TextureDilate.cs.uid @@ -0,0 +1 @@ +uid://bfiqjmyt04ils diff --git a/Runtime/Procedural/Baking/TextureMerger.cs b/Runtime/Procedural/Baking/TextureMerger.cs index ae9c440..8262b4c 100644 --- a/Runtime/Procedural/Baking/TextureMerger.cs +++ b/Runtime/Procedural/Baking/TextureMerger.cs @@ -122,6 +122,7 @@ namespace Rokojori X_textureMergerViewport.Size = (Vector2I) textureSize; X_textureMergerViewport.OwnWorld3D = true; X_textureMergerViewport.TransparentBg = true; + X_textureMergerViewport.UseHdr2D = true; } diff --git a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs index b1f1b02..a8b588c 100644 --- a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs +++ b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs @@ -37,10 +37,10 @@ namespace Rokojori } } - public static TextureCombinerBuffer From( Texture2D texture ) + public static TextureCombinerBuffer From( Texture2D texture, int srgbConversion = 0) { var buffer = Create( texture.GetWidth(), texture.GetHeight() ); - buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight() ); + buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight(), srgbConversion ); return buffer; } @@ -73,17 +73,34 @@ namespace Rokojori } - public void CopyFrom( Image image, int sourceX, int sourceY, int ownX, int ownY, int w, int h ) + public void CopyFrom( Image image, int sourceX, int sourceY, int ownX, int ownY, int w, int h, int srgbConversion = 0 ) { - - for ( int i = 0; i < w; i++ ) + if ( srgbConversion != 0 ) { - for ( int j = 0; j < h; j++ ) + var gamma = Mathf.Pow( 2.2f, srgbConversion ); + + for ( int i = 0; i < w; i++ ) { - var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j ); + for ( int j = 0; j < h; j++ ) + { + var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j ); + sourcePixel = sourcePixel.Gamma( gamma ); + SetAt( ownX + i, ownY + j, sourcePixel ); - SetAt( ownX + i, ownY + j, sourcePixel ); + } + } + } + else + { + + for ( int i = 0; i < w; i++ ) + { + for ( int j = 0; j < h; j++ ) + { + var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j ); + SetAt( ownX + i, ownY + j, sourcePixel ); + } } } } diff --git a/Runtime/Rendering/Compositor/CompositorEffects/BoxBlur/BoxBlurEffect.cs b/Runtime/Rendering/Compositor/CompositorEffects/BoxBlur/BoxBlurEffect.cs new file mode 100644 index 0000000..6f94e71 --- /dev/null +++ b/Runtime/Rendering/Compositor/CompositorEffects/BoxBlur/BoxBlurEffect.cs @@ -0,0 +1,134 @@ + +using Godot; +using Godot.Collections; +using System.Collections.Generic; + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class BoxBlurEffect:RDGraphCompositorEffect + { + public BoxBlurEffect():base() + { + Initialize(); + } + + [Export( PropertyHint.Range, "0,1")] + public float intensity = 1f; + + [Export( PropertyHint.Range, "0,100")] + public float noise = 0f; + + [Export( PropertyHint.Range, "1,100")] + public int kernelOffset = 5; + + [Export( PropertyHint.Range, "1,30")] + public int kernelRadius = 2; + + [Export( PropertyHint.Range, "1,4")] + public int iterations = 1; + + + CEG_ScreenColorTexure screenColorTexture; + CEG_BufferTexture bufferTexture; + + CEG_Copy copy; + CEG_Copy copy2; + RD_BoxBlur boxBlur; + RD_BoxBlur boxBlur1; + RD_BoxBlur boxBlur2; + RD_BoxBlur boxBlur3; + + List _blurs; + + void Initialize() + { + screenColorTexture = new CEG_ScreenColorTexure( graph ); + bufferTexture = CEG_BufferTexture.ScreenSize( graph ); + + copy = new CEG_Copy( graph ); + copy2 = new CEG_Copy( graph ); + boxBlur = new RD_BoxBlur( graph ); + boxBlur1 = new RD_BoxBlur( graph ); + boxBlur2 = new RD_BoxBlur( graph ); + boxBlur3 = new RD_BoxBlur( graph ); + + _blurs = new List() + { + boxBlur, boxBlur1, boxBlur2, boxBlur3 + }; + + graph.InitializeNodes(); + + copy.SetTextureSlotInputs( screenColorTexture, bufferTexture ); + boxBlur.SetTextureSlotInputs( copy.output, copy.input ); + boxBlur1.SetTextureSlotInputs( boxBlur.output, boxBlur.input ); + boxBlur2.SetTextureSlotInputs( boxBlur1.output, boxBlur1.input ); + boxBlur3.SetTextureSlotInputs( boxBlur2.output, boxBlur2.input ); + + } + + int _lastIterations = -1; + + + protected override void ForAllViews() + { + + + SetOrderForIterations(); + + _blurs.ForEach( + blur => + { + blur.constants.Set( + intensity, + noise, + (float)kernelOffset, + (float)kernelRadius + ); + } + ); + + } + + void SetOrderForIterations() + { + iterations = Mathf.Clamp( iterations, 1, _blurs.Count ); + + if ( _lastIterations == iterations ) + { + return; + } + + var list = new List + { + screenColorTexture, + bufferTexture, + copy + }; + + for ( int i = 0; i < iterations; i++ ) + { + list.Add( _blurs[ i ] ); + } + + if ( iterations % 2 == 0 ) + { + var lastBlur = _blurs[ iterations - 1 ]; + copy2.SetTextureSlotInputs( lastBlur.output, lastBlur.input ); + list.Add( copy2 ); + } + + _lastIterations = iterations; + + + + graph.SetProcessOrder( list ); + + } + + + + } +} \ No newline at end of file diff --git a/Runtime/Rendering/Compositor/CompositorEffects/BoxBlur/BoxBlurEffect.cs.uid b/Runtime/Rendering/Compositor/CompositorEffects/BoxBlur/BoxBlurEffect.cs.uid new file mode 100644 index 0000000..86911ba --- /dev/null +++ b/Runtime/Rendering/Compositor/CompositorEffects/BoxBlur/BoxBlurEffect.cs.uid @@ -0,0 +1 @@ +uid://dqsxgtt4e6vwu diff --git a/Runtime/Rendering/Context/RDContext.Messages.cs b/Runtime/Rendering/Context/RDContext.Messages.cs index 950e2ed..9cc18f3 100644 --- a/Runtime/Rendering/Context/RDContext.Messages.cs +++ b/Runtime/Rendering/Context/RDContext.Messages.cs @@ -25,7 +25,7 @@ namespace Rokojori if ( logMessages ) { - RJLog.ErrorFull( message ); + RJLog.ErrorWithFullTrace( message ); } } @@ -37,7 +37,7 @@ namespace Rokojori if ( logMessages && Messages.GetLevel( MessageType.Warning ) >= messageLogLevel ) { - RJLog.ErrorFull( message ); + RJLog.ErrorWithFullTrace( message ); } } @@ -49,7 +49,7 @@ namespace Rokojori if ( logMessages && Messages.GetLevel( MessageType.Info ) >= messageLogLevel ) { - RJLog.Log( message ); + RJLog.LogWithTraceOffset( 1, message ); } } @@ -61,7 +61,7 @@ namespace Rokojori if ( logMessages && Messages.GetLevel( MessageType.Verbose ) >= messageLogLevel ) { - RJLog.Log( message ); + RJLog.LogWithTraceOffset( 1, message ); } } diff --git a/Runtime/Rendering/Context/RDContext.cs b/Runtime/Rendering/Context/RDContext.cs index b04a95c..973bbd4 100644 --- a/Runtime/Rendering/Context/RDContext.cs +++ b/Runtime/Rendering/Context/RDContext.cs @@ -107,12 +107,25 @@ namespace Rokojori AssignTexture( GetScreenDepthTexture(), sampler, setIndex ); } + RDTexture _missingTexture = null; + Vector2I _missingTextureSize = new Vector2I( 64, 64 ); + + public void AssignMissingTexture( RDSampler sampler = null, int setIndex = -1 ) + { + if ( _missingTexture == null ) + { + _missingTexture = RDTexture.Create( this, _missingTextureSize, RenderingDevice.DataFormat.R16G16B16A16Sfloat ); + _missingTexture.SetData( new Color( 1, 0, 1, 1 ) ); + } + + AssignTexture( _missingTexture, sampler, setIndex ); + } public void AssignTexture( RDTexture texture, RDSampler sampler = null, int setIndex = -1 ) { // effect.Verbose( "Incoming Uniform Index", setIndex ); - if ( setIndex == -1 ) + if ( setIndex == -1 ) { setIndex = _uniformSets.Count; } @@ -263,6 +276,7 @@ namespace Rokojori if ( pushConstants != null ) { + Verbose( "Set constants", pushConstants.size ); computeList.SetPushConstants( pushConstants ); } diff --git a/Runtime/Rendering/Objects/RDPushConstants.cs b/Runtime/Rendering/Objects/RDPushConstants.cs index 5d0cefc..2a17f18 100644 --- a/Runtime/Rendering/Objects/RDPushConstants.cs +++ b/Runtime/Rendering/Objects/RDPushConstants.cs @@ -64,6 +64,8 @@ namespace Rokojori _AddVector4( (Vector4) objects[ i ] ); } } + + } protected void _AddFloat( float value ) @@ -85,7 +87,7 @@ namespace Rokojori if ( _intIndex >= _ints.Count ) { _ints.Add( value ); - _intIndex = _floats.Count; + _intIndex = _ints.Count; } else { @@ -217,9 +219,9 @@ namespace Rokojori Array.Copy( intBytes, 0, _bytes, i * 4 + floatsOffset, 4 ); } - var intsOffset = _ints.Count * 4; + var intsOffset = floatsOffset + _ints.Count * 4; - for ( int i = intsOffset + floatsOffset; i < _bytes.Length; i++ ) + for ( int i = intsOffset; i < _bytes.Length; i++ ) { _bytes[ i ] = 0; } diff --git a/Runtime/Rendering/Objects/RDTexture.cs b/Runtime/Rendering/Objects/RDTexture.cs index 525c2ab..e150bb3 100644 --- a/Runtime/Rendering/Objects/RDTexture.cs +++ b/Runtime/Rendering/Objects/RDTexture.cs @@ -113,6 +113,7 @@ namespace Rokojori public int width => (int) format.Width; public int height => (int) format.Height; + public int maxDimension => Mathf.RoundToInt( Mathf.Max( width, height ) ); public RenderingDevice.DataFormat dataFormat => format.Format; public Image.Format imageFormat => RDTextureFormats.DataFormatToImageFormat( dataFormat ); diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl new file mode 100644 index 0000000..bbcb241 --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl @@ -0,0 +1,99 @@ +#[compute] +#version 450 + +layout( local_size_x = 8, local_size_y = 8, local_size_z = 1 ) in; + +layout( rgba16f, set = 0, binding = 0 ) +uniform image2D inputImage; + +layout( rgba16f, set = 1, binding = 0 ) +uniform image2D outputImage; + + +layout( push_constant, std430 ) +uniform Parameters +{ + float intensity; + float noise; + float kernelOffset; + float kernelRadius; + +} parameters; + + +float randomFloat( vec2 uv ) +{ + return fract( sin( dot( uv.xy, vec2( 12.9898,78.233 ) ) ) * 43758.5453123 ); +} + +vec2 random( vec2 uv ) +{ + float x = randomFloat( uv ); + float y = randomFloat( uv + vec2( 10002, -23589 ) ); + + return vec2( x, y ) * 2.0 - vec2( 1.0, 1.0 ); +} + + + +void main( ) +{ + ivec2 size = imageSize( inputImage ); + ivec2 pixelUV = ivec2( gl_GlobalInvocationID.xy ); + + if ( any( greaterThanEqual( pixelUV, size ) ) ) + { + return; + } + + vec4 color = vec4( 0.0 ); + + int kernelRadius = int( parameters.kernelRadius ); + int kernelOffset = int( parameters.kernelOffset ); + + if ( parameters.noise > 0.0 ) + { + for ( int x = -kernelRadius; x <= kernelRadius; x++ ) + { + for ( int y = -kernelRadius; y <= kernelRadius; y++ ) + { + ivec2 xy = ivec2( x, y ) * kernelOffset; + ivec2 kernelUV = pixelUV + xy; + + kernelUV += ivec2( random( kernelUV ) * parameters.noise ); + + kernelUV.x = clamp( kernelUV.x, 0, size.x - 1 ); + kernelUV.y = clamp( kernelUV.y, 0, size.y - 1 ); + + color += imageLoad( inputImage, kernelUV ); + } + } + } + else + { + for ( int x = -kernelRadius; x <= kernelRadius; x++ ) + { + for ( int y = -kernelRadius; y <= kernelRadius; y++ ) + { + ivec2 xy = ivec2( x, y ) * kernelOffset; + ivec2 kernelUV = pixelUV + xy; + + kernelUV.x = clamp( kernelUV.x, 0, size.x - 1 ); + kernelUV.y = clamp( kernelUV.y, 0, size.y - 1 ); + + color += imageLoad( inputImage, kernelUV ); + } + } + } + + + + int numPixels = ( kernelRadius * 2 + 1 ) * ( kernelRadius * 2 + 1 ); + + color /= numPixels; + + vec4 originalColor = imageLoad( inputImage, pixelUV ); + vec4 mixedColor = mix( originalColor, color, parameters.intensity ); + + imageStore( outputImage, pixelUV, mixedColor ); +} \ No newline at end of file diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl.import b/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl.import new file mode 100644 index 0000000..24a4803 --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://c1xombr20y7ql" +path="res://.godot/imported/BoxBlur.glsl-de744fa8bcca6e5a6cafa48c0fa412eb.res" + +[deps] + +source_file="res://addons/rokojori_action_library/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl" +dest_files=["res://.godot/imported/BoxBlur.glsl-de744fa8bcca6e5a6cafa48c0fa412eb.res"] + +[params] + diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/RG_BoxBlur.cs b/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/RG_BoxBlur.cs new file mode 100644 index 0000000..63deb06 --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/RG_BoxBlur.cs @@ -0,0 +1,17 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + public class RD_BoxBlur:CEG_ImageProcessor + { + public static readonly string shaderPath = + RDGraph.Path( "Nodes/Processors/Blurs/BoxBlur/BoxBlur.glsl" ); + + public RD_BoxBlur( RDGraph graph ):base( graph, shaderPath ) + {} + + + } +} \ No newline at end of file diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/RG_BoxBlur.cs.uid b/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/RG_BoxBlur.cs.uid new file mode 100644 index 0000000..ffb86dc --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Blurs/BoxBlur/RG_BoxBlur.cs.uid @@ -0,0 +1 @@ +uid://b1vkp54fq4kt7 diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Copy/Copy.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/Copy/Copy.glsl index 4c1e2b8..755cb47 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/Copy/Copy.glsl +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Copy/Copy.glsl @@ -1,12 +1,12 @@ #[compute] #version 450 -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; +layout( local_size_x = 8, local_size_y = 8, local_size_z = 1 ) in; -layout(rgba16, set = 0, binding = 0) +layout( rgba16, set = 0, binding = 0 ) uniform restrict readonly image2D inputImage; -layout(rgba16, set = 1, binding = 0) +layout( rgba16, set = 1, binding = 0 ) uniform restrict writeonly image2D outputImage; void main() diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_BufferTexture.cs b/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_BufferTexture.cs index 24a4a24..f829841 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_BufferTexture.cs +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_BufferTexture.cs @@ -131,7 +131,9 @@ namespace Rokojori public static CEG_BufferTexture From( RDGraph graph, RDTexture texture ) { var creator = new CEG_TextureCreator_Reference( texture ); - return new CEG_BufferTexture( graph, creator ); + var t = new CEG_BufferTexture( graph, creator ); + t._texture = texture; + return t; } public override void Process() diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_ImageProcessor.cs b/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_ImageProcessor.cs index 9b74dff..056c7d8 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_ImageProcessor.cs +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_ImageProcessor.cs @@ -29,6 +29,14 @@ namespace Rokojori imageProcessorBefore.output.ConnectTo( output ); } + public void AddTextureSlotInput( RDGraphTextureSlotInput inputSlot ) + { + var slot = new CompositorEffectGraphTextureSlot( this ); + _textureSlots.Add( slot ); + + inputSlot.ConnectTo( slot ); + } + } } \ No newline at end of file diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/CEG_JFAAssign.cs.uid b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/CEG_JFAAssign.cs.uid new file mode 100644 index 0000000..898417c --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/CEG_JFAAssign.cs.uid @@ -0,0 +1 @@ +uid://6scrdbsfh3vj diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl index 7bc0aaf..0616c53 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl @@ -7,18 +7,22 @@ layout( rgba16, set = 0, binding = 0 ) uniform restrict readonly image2D inputImage; layout( rgba16, set = 1, binding = 0 ) -uniform restrict readonly image2D originalImage; - -layout( rgba16, set = 2, binding = 0 ) uniform restrict writeonly image2D outputImage; -void main() -{ +layout( rgba16, set = 2, binding = 0 ) +uniform restrict readonly image2D originalImage; + +void main() +{ ivec2 currentPosition = ivec2( gl_GlobalInvocationID.xy ); - vec4 currentPixel = imageLoad( inputImage, currentPosition ); + vec4 currentPixel = imageLoad( inputImage, currentPosition ); + ivec2 seedPosition = ivec2( packUnorm2x16( currentPixel.xy ), packUnorm2x16( currentPixel.zw ) ); - vec4 originalPixel = imageLoad( originalImage, seedPosition ); + vec4 colorPixel = imageLoad( originalImage, seedPosition ); + vec4 originalPixel = imageLoad( originalImage, currentPosition ); - imageStore(outputImage, currentPosition, vec4(originalPixel.xyz, originalPixel.a)); + vec2 seedUV = vec2( seedPosition ) / imageSize( inputImage ); + + imageStore( outputImage, currentPosition, vec4( colorPixel.rgb, originalPixel.a) ); } diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Initialize.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Initialize.glsl index 4338f23..fe5d825 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Initialize.glsl +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Initialize.glsl @@ -25,9 +25,11 @@ void main() { vec4 packedZero = vec4( unpackUnorm2x16( 0 ), unpackUnorm2x16( 0 ) ); imageStore( outputImage, currentPosition, packedZero ); + // imageStore( outputImage, currentPosition, vec4( 1, 0, 0, 1 ) ); return; } vec4 packedPosition = vec4( unpackUnorm2x16( currentPosition.x ), unpackUnorm2x16( currentPosition.y ) ); imageStore( outputImage, currentPosition, packedPosition); + // imageStore( outputImage, currentPosition, vec4( 0, 1, 0, 1 ) ); } diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Iterate.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Iterate.glsl index de274a7..3ece9b4 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Iterate.glsl +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Iterate.glsl @@ -9,8 +9,8 @@ uniform restrict readonly image2D inputImage; layout(rgba16, set = 1, binding = 0) uniform restrict writeonly image2D outputImage; -layout(std430, set = 2, binding = 0) -buffer restrict readonly DistanceParameters +layout( push_constant, std430 ) +uniform DistanceParameters { int jump; @@ -21,7 +21,7 @@ void main() ivec2 currentPosition = ivec2( gl_GlobalInvocationID.xy ); ivec2 imageSize = imageSize( inputImage ); - float distanceToClosestSeed = 1.0f / 0.0f; + float distanceToClosestSeed = 100000.0; vec4 closestSeed = vec4( unpackUnorm2x16( 0 ), unpackUnorm2x16( 0 ) ); ivec2 jump = ivec2( distanceParameters.jump, distanceParameters.jump ); diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Logic/RG_SwapRepeat.cs b/Runtime/Rendering/RenderGraph/Nodes/Processors/Logic/RG_SwapRepeat.cs new file mode 100644 index 0000000..890ec46 --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Logic/RG_SwapRepeat.cs @@ -0,0 +1,96 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + public class RG_SwapRepeat:RGGraphProcessor + { + protected RG_TextureSlotEditable _input; + protected RG_TextureSlotEditable _output; + + public CompositorEffectGraphTextureSlot input => _input; + public CompositorEffectGraphTextureSlot output => _output; + + + public CEG_ImageProcessor imageProcessor; + public int repeats = 1; + + public System.Action onStart; + public System.Action onPreProcess; + public System.Action onPostProcess; + public System.Action onEnd; + + public RG_SwapRepeat( RDGraph graph ):base( graph ) + { + _input = new RG_TextureSlotEditable( this ); + _output = new RG_TextureSlotEditable( this ); + } + + public void SetTextureSlotInputs( RDGraphTextureSlotInput inputSlot, RDGraphTextureSlotInput outputSlot ) + { + inputSlot.ConnectTo( input ); + outputSlot.ConnectTo( output ); + } + + public void SetTextureSlotInputs( CEG_ImageProcessor imageProcessorBefore ) + { + imageProcessorBefore.input.ConnectTo( input ); + imageProcessorBefore.output.ConnectTo( output ); + } + + public override void Process() + { + if ( onStart != null ) + { + onStart(); + } + + var cachedInputTexture = input.ResolveTexture(); + var cachedOutputTexture = output.ResolveTexture(); + + imageProcessor.SetTextureSlotInputs( input, output ); + + for ( int i = 0; i < repeats; i++ ) + { + graph.context.Verbose( "Repeat:", i ); + + if ( i % 2 == 0 ) + { + _input.SetTexture( cachedInputTexture ); + _output.SetTexture( cachedOutputTexture ); + } + else + { + _input.SetTexture( cachedOutputTexture ); + _output.SetTexture( cachedInputTexture ); + } + + if ( onPreProcess != null ) + { + onPreProcess( i ); + } + + imageProcessor.Process(); + + if ( onPostProcess != null ) + { + onPostProcess( i ); + } + } + + _input.SetTexture( cachedInputTexture ); + _output.SetTexture( cachedOutputTexture ); + + if ( onEnd != null ) + { + onEnd(); + } + + + + } + + + } +} \ No newline at end of file diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Logic/RG_SwapRepeat.cs.uid b/Runtime/Rendering/RenderGraph/Nodes/Processors/Logic/RG_SwapRepeat.cs.uid new file mode 100644 index 0000000..790890a --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Logic/RG_SwapRepeat.cs.uid @@ -0,0 +1 @@ +uid://bmpqy38ty2nlx diff --git a/Runtime/Rendering/RenderGraph/RDGraph.cs b/Runtime/Rendering/RenderGraph/RDGraph.cs index 665c612..4080eca 100644 --- a/Runtime/Rendering/RenderGraph/RDGraph.cs +++ b/Runtime/Rendering/RenderGraph/RDGraph.cs @@ -54,14 +54,20 @@ namespace Rokojori public void ProcessForView() { + var index = 1; + var num = _processOrder.Count; + _processOrder.ForEach( p => { - context.Verbose( p.GetType() ); + context.Verbose( index + "/" + num, p.GetType() ); p.Process(); + index++; } ); + context.Verbose( "Render done" ); + } } } \ No newline at end of file diff --git a/Runtime/Rendering/RenderGraph/RDGraphTextureSlot.cs b/Runtime/Rendering/RenderGraph/RDGraphTextureSlot.cs index 68ef80c..11794bc 100644 --- a/Runtime/Rendering/RenderGraph/RDGraphTextureSlot.cs +++ b/Runtime/Rendering/RenderGraph/RDGraphTextureSlot.cs @@ -19,7 +19,7 @@ namespace Rokojori public RDSampler sampler; - RDTexture _texture; + protected RDTexture _texture; public RDTexture GetTexture() { @@ -59,4 +59,14 @@ namespace Rokojori slot.SetInput( this ); } } + + public class RG_TextureSlotEditable:CompositorEffectGraphTextureSlot + { + public RG_TextureSlotEditable( RGGraphProcessor processor ):base( processor ){} + + public void SetTexture( RDTexture texture ) + { + _texture = texture; + } + } } \ No newline at end of file diff --git a/Runtime/Rendering/RenderGraph/RDShaderProcessor.cs b/Runtime/Rendering/RenderGraph/RDShaderProcessor.cs index ccd1920..6085d51 100644 --- a/Runtime/Rendering/RenderGraph/RDShaderProcessor.cs +++ b/Runtime/Rendering/RenderGraph/RDShaderProcessor.cs @@ -22,11 +22,11 @@ namespace Rokojori protected override void OnInitialize() { - graph.context.Verbose( "Trying to load shader: ", _shaderPath ); + graph.context.Verbose( GetType().Name, "Trying to load shader: ", _shaderPath ); if ( _shaderPath == null ) { - graph.context.Error( "_shaderPath == null" ); + graph.context.Error( GetType().Name, "_shaderPath == null" ); return; } @@ -34,7 +34,7 @@ namespace Rokojori if ( glslFile == null ) { - graph.context.Error( "Couldn't load shader at path:", _shaderPath ); + graph.context.Error( GetType().Name, "Couldn't load shader at path:", _shaderPath ); return; } @@ -42,7 +42,7 @@ namespace Rokojori if ( _shader == null ) { - graph.context.Error( "Couldn't create shader from code, path:", _shaderPath ); + graph.context.Error( GetType().Name, "Couldn't create shader from code, path:", _shaderPath ); return; } @@ -50,11 +50,11 @@ namespace Rokojori if ( _shader == null ) { - graph.context.Error( "Couldn't create pipeline from compiled shader, path:", _shaderPath ); + graph.context.Error( GetType().Name, "Couldn't create pipeline from compiled shader, path:", _shaderPath ); return; } - graph.context.Verbose( "Created shader at path: ", _shaderPath ); + graph.context.Verbose( GetType().Name, "Created shader at path: ", _shaderPath ); } public override void Process() @@ -65,18 +65,49 @@ namespace Rokojori context.CalculateSceneComputeGroups( _groupSize ); context.SetShaderAndPipeline( _shader, _pipeline ); + context.Verbose( GetType().Name, "Setting texture uniforms", _textureSlots.Count ); + + int index = 0; + _textureSlots.ForEach( t => { + index++; + t.ResolveTexture(); - graph.context.AssignTexture( t.GetTexture(), t.sampler ); + var texture = t.GetTexture(); + + if ( texture == null || ! texture.rid.IsValid ) + { + if ( texture == null ) + { + context.Error( index, "Texture is null" ); + } + else + { + context.Error( index, "Texture is not valid:", texture.rid ); + } + + graph.context.AssignMissingTexture( t.sampler ); + return; + } + + graph.context.AssignTexture( texture, t.sampler ); + } ); + if ( _constants.size > 0 ) - { + { + context.Verbose( GetType().Name, "Setting constants", _constants.size ); context.pushConstants = _constants; - } + } + else + { + context.Verbose( GetType().Name, "No constants" ); + } + context.Verbose( GetType().Name, "Process Compute Program", _constants.size ); context.ProcessComputeProgram(); } }