diff --git a/Runtime/Bits/BitMath.cs b/Runtime/Bits/BitMath.cs index 318af4d..3a498f5 100644 --- a/Runtime/Bits/BitMath.cs +++ b/Runtime/Bits/BitMath.cs @@ -10,22 +10,52 @@ namespace Rokojori return ( 1 << bit ); } + public static long GetInt64BitMask( int bit ) + { + return ( 1 << bit ); + } + public static int SetBit( int value, int bitPosition ) { return value | GetInt32BitMask( bitPosition ); } + public static long SetBit( long value, int bitPosition ) + { + return value | GetInt64BitMask( bitPosition ); + } + public static int UnsetBit( int value, int bitPosition ) { return value & ~GetInt32BitMask( bitPosition ); } + public static long UnsetBit( long value, int bitPosition ) + { + return value & ~GetInt64BitMask( bitPosition ); + } + public static bool IsBitSet( int value, int bitPosition ) { var mask = GetInt32BitMask( bitPosition ); return ( value & mask ) == mask; } + public static bool IsBitSet( long value, int bitPosition ) + { + var mask = GetInt64BitMask( bitPosition ); + return ( value & mask ) == mask; + } + + public static bool IsMaskSet( int value, int mask ) + { + return ( value & mask ) == mask; + } + + public static bool IsMaskSet( long value, long mask ) + { + return ( value & mask ) == mask; + } } } \ No newline at end of file diff --git a/Runtime/Logging/RJLog.cs b/Runtime/Logging/RJLog.cs index 31ca7da..55d3db4 100644 --- a/Runtime/Logging/RJLog.cs +++ b/Runtime/Logging/RJLog.cs @@ -145,6 +145,13 @@ namespace Rokojori GD.PrintRich( trace ); } + static void LogErrorWithFullTrace( string message ) + { + var trace = GetFullTrace(); + GD.PrintErr("\n" + message ); + GD.PrintRich( trace ); + } + static void LogErrorMessage( string message, int frameIndex = 3 ) { var trace = GetTrace( frameIndex ); @@ -218,6 +225,11 @@ namespace Rokojori LogErrorMessage( GetLogString( objects ) ); } + public static void ErrorFull( params object[] objects) + { + LogErrorWithFullTrace( GetLogString( objects ) ); + } + public static void Error( Node node, params object[] objects) { LogErrorMessage( "" + HierarchyName.Of( node ) + "\n" + GetLogString( objects ), 4 ); diff --git a/Runtime/Procedural/Baking/GrabTexture.cs b/Runtime/Procedural/Baking/GrabTexture.cs index 8b29cd6..899f604 100644 --- a/Runtime/Procedural/Baking/GrabTexture.cs +++ b/Runtime/Procedural/Baking/GrabTexture.cs @@ -54,7 +54,15 @@ namespace Rokojori public Callable GrabTextureButton => Callable.From( async () => { - texture2D = await alphaGrabTestEffect.GetImageTexture( async ()=> await this.RequestNextFrame() ); + var result = await alphaGrabTestEffect.GetImageTexture( async ()=> await this.RequestNextFrame() ); + + if ( result == null ) + { + this.LogError( "No texture" ); + return; + } + + texture2D = result; } ); diff --git a/Runtime/Procedural/Baking/GrabTexture2.cs b/Runtime/Procedural/Baking/GrabTexture2.cs new file mode 100644 index 0000000..b155425 --- /dev/null +++ b/Runtime/Procedural/Baking/GrabTexture2.cs @@ -0,0 +1,135 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; +using System.Linq; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class GrabTexture2:Action + { + [Export] + public SubViewport viewport; + + [Export] + public Texture2D target; + + [Export] + public MeshInstance3D meshInstance3D; + + + [ExportToolButton( "Grab Texture")] + public Callable GrabButton => Callable.From( + () => + { + Grab(); + } + ); + + async void 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( "Creating context" ); + var ctx = RDContext.Local(); + ctx.computeSize = viewPortSize; + ctx.messageLogLevel = Messages.GetLevel( MessageType.Verbose ); + + + this.LogInfo( "Creating textures" ); + + var outputTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); + this.LogInfo( "Usage", RDTextureFormats.UsageInfo( outputTexture.format.UsageBits ) ); + + + var inputTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); + inputTexture.SetData( viewPortData ); + + var graph = CreateGraph( ctx, inputTexture, outputTexture ); + + graph.ProcessForView(); + + ctx.SubmitAndSync(); + + var width = outputTexture.width; + var height = outputTexture.height; + var format = outputTexture.imageFormat; + + var data = outputTexture.GetData(); + + this.LogInfo( "Copying texture" ); + + ctx.SubmitAndSync(); + await this.RequestNextFrame(); + + var image = Image.CreateFromData( width, height, false, format, data ); + var buffer = TextureCombinerBuffer.From( ImageTexture.CreateFromImage( image ) ); + + target = buffer.CreateImageTexture(); + + var material3D = (StandardMaterial3D) meshInstance3D.MaterialOverride; + material3D.AlbedoTexture = target; + + ctx.CleanUp(); + + await this.RequestNextFrame(); + + + + + + } + + RDGraph CreateGraph( RDContext ctx, RDTexture it, RDTexture ot ) + { + var graph = new RDGraph( ctx ); + + var viewTexture = CEG_BufferTexture.From( graph, it ); + var bufferTexture = CEG_BufferTexture.From( graph, ot ); + + var copy = new CEG_Copy( graph ); + var radialBlur = new CEG_RadialBlur( graph ); + + graph.InitializeNodes(); + + copy.SetTextureSlotInputs( viewTexture, bufferTexture ); + radialBlur.SetTextureSlotInputs( copy.output, copy.input ); + + + graph.SetProcessOrder( + viewTexture, bufferTexture, + copy, radialBlur + ); + + radialBlur.constants.Set( + new Vector2( 0.5f, 0.5f ), + 0.5f, + 0.5f, + 16, + Vector2.Zero + ); + + return graph; + } + + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Baking/GrabTexture2.cs.uid b/Runtime/Procedural/Baking/GrabTexture2.cs.uid new file mode 100644 index 0000000..19224ee --- /dev/null +++ b/Runtime/Procedural/Baking/GrabTexture2.cs.uid @@ -0,0 +1 @@ +uid://ctj2rxanlda0d diff --git a/Runtime/Procedural/Baking/GrabTextureRD.cs b/Runtime/Procedural/Baking/GrabTextureRD.cs new file mode 100644 index 0000000..56dae7c --- /dev/null +++ b/Runtime/Procedural/Baking/GrabTextureRD.cs @@ -0,0 +1,120 @@ +using System.Collections; +using System.Collections.Generic; +using Godot; +using System; +using System.Linq; + + + +namespace Rokojori +{ + [Tool] + [GlobalClass] + public partial class GrabTextureRD:Action + { + [Export] + public SubViewport viewport; + + [Export] + public Texture2D target; + + [Export] + public MeshInstance3D meshInstance3D; + + + [ExportToolButton( "Grab Texture")] + public Callable GrabButton => Callable.From( + () => + { + Grab(); + } + ); + + async void 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(); + + this.LogInfo( "Creating context" ); + var ctx = RDContext.Local(); + ctx.messageLogLevel = Messages.GetLevel( MessageType.Verbose ); + + this.LogInfo( "Creating program" ); + ctx.SetProgramFromPath( CEG_AlphaColorDilation.shaderPath ); + + this.LogInfo( "Creating textures" ); + + var outputTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); + this.LogInfo( "Usage", RDTextureFormats.UsageInfo( outputTexture.format.UsageBits ) ); + outputTexture.SetData( new Color( 1, 1, 1, 1 ) ); + + + + // var inputTexture = RDTexture.CreateCopyFrom( ctx, viewport ); + var inputTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat ); + inputTexture.SetData( viewPortData ); + // inputTexture.SetData( new Color( 0, 1, 0, 1 ) ); + + this.LogInfo( "Assigning input texture:", ctx.shader, ctx.shader.rid ); + ctx.AssignTexture( inputTexture ); + + this.LogInfo( "Assigning output texture" ); + ctx.AssignTexture( outputTexture ); + + this.LogInfo( "Compute group sizes" ); + ctx.CalculateComputeGroups( 8, viewport.Size ); + + this.LogInfo( "Process compute program" ); + ctx.ProcessComputeProgram(); + + this.LogInfo( "Waiting to render" ); + + ctx.SubmitAndSync(); + + var width = outputTexture.width; + var height = outputTexture.height; + var format = outputTexture.imageFormat; + + var data = outputTexture.GetData(); + data = data.ToList().ToArray(); + + this.LogInfo( "Copying texture" ); + + ctx.SubmitAndSync(); + + + + await this.RequestNextFrame(); + + var image = Image.CreateFromData( width, height, false, format, data ); + var buffer = TextureCombinerBuffer.From( ImageTexture.CreateFromImage( image ) ); + + target = buffer.CreateImageTexture(); + + var material3D = (StandardMaterial3D) meshInstance3D.MaterialOverride; + material3D.AlbedoTexture = target; + + ctx.CleanUp(); + + await this.RequestNextFrame(); + + + + + + } + + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Baking/GrabTextureRD.cs.uid b/Runtime/Procedural/Baking/GrabTextureRD.cs.uid new file mode 100644 index 0000000..acc05ad --- /dev/null +++ b/Runtime/Procedural/Baking/GrabTextureRD.cs.uid @@ -0,0 +1 @@ +uid://cl0fx4gpluvhh diff --git a/Runtime/Rendering/Compositor/CompositorEffects/ChromaticAberation/ChromaticAberation.cs b/Runtime/Rendering/Compositor/CompositorEffects/ChromaticAberation/ChromaticAberation.cs index b6a5c76..b4b6e48 100644 --- a/Runtime/Rendering/Compositor/CompositorEffects/ChromaticAberation/ChromaticAberation.cs +++ b/Runtime/Rendering/Compositor/CompositorEffects/ChromaticAberation/ChromaticAberation.cs @@ -14,16 +14,6 @@ namespace Rokojori Initialize(); } - - [Export] - public float intensity = 0.5f; - - [Export] - public float shiftAll = 0.5f; - - [Export] - public float unshiftCenter = 16f; - [Export] public Vector2 rShift = new Vector2( -0.001f, 0.0f ); @@ -33,6 +23,16 @@ namespace Rokojori [Export] public Vector2 bShift = new Vector2( 0.001f, 0.0f ); + + [Export] + public float intensity = 0.5f; + + [Export] + public float shiftAll = 0.5f; + + [Export] + public float unshiftCenter = 16f; + CEG_ScreenColorTexure screenColorTexture; @@ -52,8 +52,6 @@ namespace Rokojori graph.InitializeNodes(); - - copy.SetTextureSlotInputs( screenColorTexture, bufferTexture ); chromaticAberation.SetTextureSlotInputs( copy.output, copy.input ); @@ -68,12 +66,13 @@ namespace Rokojori protected override void ForAllViews() { chromaticAberation.constants.Set( - intensity, - shiftAll, - unshiftCenter, + rShift, gShift, - bShift + bShift, + intensity, + shiftAll, + unshiftCenter ); } diff --git a/Runtime/Rendering/Compositor/CompositorEffects/TextureDilation/JFA_Assign.glsl b/Runtime/Rendering/Compositor/CompositorEffects/TextureDilation/JFA_Assign.glsl index 1573125..af524f8 100644 --- a/Runtime/Rendering/Compositor/CompositorEffects/TextureDilation/JFA_Assign.glsl +++ b/Runtime/Rendering/Compositor/CompositorEffects/TextureDilation/JFA_Assign.glsl @@ -31,7 +31,7 @@ void main() return; } - vec4 original_pixel = imageLoad(originalImage, current_seed_position); + vec4 original_pixel = imageLoad( originalImage, current_seed_position ); // The current pixel is on the edge of the outline, outer side if (distance_to_seed > outlinesSize - 1.0f) diff --git a/Runtime/Rendering/Compositor/SingleShaderCompositorEffect.cs b/Runtime/Rendering/Compositor/SingleShaderCompositorEffect.cs index 483baf5..7b6de31 100644 --- a/Runtime/Rendering/Compositor/SingleShaderCompositorEffect.cs +++ b/Runtime/Rendering/Compositor/SingleShaderCompositorEffect.cs @@ -58,7 +58,7 @@ namespace Rokojori protected override void ForAllViews() { - context.CalculateComputeGroups( _groupSize ); + context.CalculateSceneComputeGroups( _groupSize ); SetConstants(); } diff --git a/Runtime/Rendering/Context/RDContext.CleanUp.cs b/Runtime/Rendering/Context/RDContext.CleanUp.cs index 78b6f8a..4f53932 100644 --- a/Runtime/Rendering/Context/RDContext.CleanUp.cs +++ b/Runtime/Rendering/Context/RDContext.CleanUp.cs @@ -16,6 +16,24 @@ namespace Rokojori Warning( "ro == null, couldn't clean up: ", info ); return; } + + if ( ! ro.rid.IsValid ) + { + Verbose( "Not valid rid:", ro.rid ); + return; + } + + if ( ro is RDPipeline ) + { + Verbose( "Not cleaning pipelines" ); + return; + } + + if ( ro is RDUniformSet ) + { + Verbose( "Not cleaning uniform sets" ); + return; + } Verbose( "Cleaning up: ", info, ro.rid ); renderingDevice.FreeRid( ro.rid ); @@ -29,7 +47,7 @@ namespace Rokojori _cleanUps.ForEach( c => { - Free( c, "_cleanUps[" + index + "]"); + Free( c, _cleanUpInfo[ index ] ); index ++; } ); diff --git a/Runtime/Rendering/Context/RDContext.Messages.cs b/Runtime/Rendering/Context/RDContext.Messages.cs index 23cfe0f..950e2ed 100644 --- a/Runtime/Rendering/Context/RDContext.Messages.cs +++ b/Runtime/Rendering/Context/RDContext.Messages.cs @@ -25,7 +25,7 @@ namespace Rokojori if ( logMessages ) { - RJLog.Log( message ); + RJLog.ErrorFull( message ); } } @@ -37,7 +37,7 @@ namespace Rokojori if ( logMessages && Messages.GetLevel( MessageType.Warning ) >= messageLogLevel ) { - RJLog.Log( message ); + RJLog.ErrorFull( message ); } } diff --git a/Runtime/Rendering/Context/RDContext.cs b/Runtime/Rendering/Context/RDContext.cs index fa64b91..b04a95c 100644 --- a/Runtime/Rendering/Context/RDContext.cs +++ b/Runtime/Rendering/Context/RDContext.cs @@ -6,19 +6,36 @@ namespace Rokojori { public partial class RDContext { + protected RenderingDevice _renderingDevice; public RenderingDevice renderingDevice => _renderingDevice; - + + protected bool _localRenderingDevice; + public bool isLocalRenderingDevice => _localRenderingDevice; + protected RDShader _shader; public RDShader shader => _shader; protected RDPipeline _pipeline; public RDPipeline pipeline => _pipeline; + public static RDContext Local() + { + var ctx = new RDContext(); + ctx.Initialize( true ); + return ctx; + } + public void Initialize( bool local = false) { + _localRenderingDevice = local; _renderingDevice = local ? RenderingServer.Singleton.CreateLocalRenderingDevice(): RenderingServer.Singleton.GetRenderingDevice(); + + if ( _renderingDevice == null ) + { + Error( "Could not initialize rendering device" ); + } } @@ -52,7 +69,18 @@ namespace Rokojori return RDTexture.Depth( this ); } - + public void SetProgram( RDProgram p ) + { + SetShaderAndPipeline( p.shader, p.pipeline ); + } + + public void SetProgramFromPath( string path ) + { + Verbose( "Creating program:", path ); + var program = RDProgram.FromPath( this, path ); + SetProgram( program ); + } + public void SetShaderAndPipeline( RDShader shader, RDPipeline pipeline ) { if ( shader == null || pipeline == null ) @@ -77,7 +105,8 @@ namespace Rokojori public void AssignScreenDepthTexture( RDSampler sampler = null, int setIndex = -1 ) { AssignTexture( GetScreenDepthTexture(), sampler, setIndex ); - } + } + public void AssignTexture( RDTexture texture, RDSampler sampler = null, int setIndex = -1 ) { @@ -110,33 +139,111 @@ namespace Rokojori _uniformSets.Add( uniformSet ); } + public void CreateUniformaSet( params RDUniform[] uniforms ) + { + var setIndex = _uniformSets.Count; + _CreateUniformSetRid( setIndex, uniforms ); + } + + public Rid _CreateUniformSetRid( int index, params RDUniform[] uniforms ) + { + var array = new Godot.Collections.Array(); + array.AddRange( uniforms ); + + if ( ! isLocalRenderingDevice ) + { + return UniformSetCacheRD.GetCache( shader.rid, (uint) index, array ); + } + else + { + return renderingDevice.UniformSetCreate( array, shader.rid, (uint) index ); + } + + } + public void Clear() { _uniformSets.Clear(); pushConstants = null; } + public Vector2I computeSize = new Vector2I( 512, 512 ); + + public Vector2I GetComputeSize() + { + if ( _sceneBuffers != null ) + { + return _sceneBuffers.GetInternalSize(); + } + + return computeSize; + } + public void SetComputeGroups( Vector3I groups ) { this._groups = groups; } - public void CalculateComputeGroups( int groupSize ) + public void CalculateSceneComputeGroups( int groupSize ) { - CalculateComputeGroups( new Vector3I( groupSize, groupSize, 0 ) ); + var size = GetComputeSize(); + CalculateComputeGroups( new Vector3I( groupSize, groupSize, 0 ), size ); } - public void CalculateComputeGroups( Vector3I groupSize ) + public void CalculateSceneComputeGroups( Vector3I groupSize ) { - var size = sceneBuffers.GetInternalSize(); + var size = GetComputeSize(); + CalculateComputeGroups( groupSize, size ); + } + public void CalculateComputeGroups( int groupSize, Vector2I size ) + { + CalculateComputeGroups( new Vector3I( groupSize, groupSize, 0 ), size ); + } + + public void CalculateComputeGroups( Vector3I groupSize, Vector2I size ) + { var xGroups = Mathf.CeilToInt( size.X / (float) groupSize.X ); var yGroups = groupSize.Y == 0 ? 1 : Mathf.CeilToInt( size.Y / (float) groupSize.Y ); - var zGroups = groupSize.Z == 0 ? 1 : Mathf.CeilToInt( size.Y / (float) groupSize.Y ); + var zGroups = 1; SetComputeGroups( new Vector3I( xGroups, yGroups, zGroups ) ); } + public void Submit() + { + if ( ! isLocalRenderingDevice ) + { + Error( "You can only submit or sync in non-local rendering devices" ); + return; + } + + renderingDevice.Submit(); + } + + public void Sync() + { + if ( ! isLocalRenderingDevice ) + { + Error( "You can only submit or sync in non-local rendering devices" ); + return; + } + + renderingDevice.Sync(); + } + + public void SubmitAndSync() + { + if ( ! isLocalRenderingDevice ) + { + Error( "You can only submit or sync in non-local rendering devices" ); + return; + } + + Submit(); + Sync(); + } + public void ProcessComputeProgram() { try diff --git a/Runtime/Rendering/Objects/RDProgram.cs b/Runtime/Rendering/Objects/RDProgram.cs index 9e4634f..18230ed 100644 --- a/Runtime/Rendering/Objects/RDProgram.cs +++ b/Runtime/Rendering/Objects/RDProgram.cs @@ -7,6 +7,14 @@ namespace Rokojori public class RDProgram { + protected RDContext _context; + public RDContext context => _context; + + public RDProgram( RDContext context ) + { + _context = context; + } + public enum Type { VertexFragment, @@ -17,9 +25,32 @@ namespace Rokojori public Type type => _type; protected RDShader _shader; - public RDShader shader; + public RDShader shader => _shader; protected RDPipeline _pipeline; - public RDPipeline pipeline; + public RDPipeline pipeline => _pipeline; + + public static RDProgram FromPath( RDContext context, string path ) + { + var p = new RDProgram( context ); + + p._shader = RDShader.FromPath( context, path ); + + if ( p._shader == null || ! p._shader.rid.IsValid ) + { + context.Error( "Invalid shader", path ); + return null; + } + + p._pipeline = RDPipeline.Create( context, p._shader ); + + if ( p._pipeline == null || ! p._pipeline.rid.IsValid ) + { + context.Error( "Invalid pipeline", path ); + return null; + } + + return p; + } } } \ No newline at end of file diff --git a/Runtime/Rendering/Objects/RDShader.cs b/Runtime/Rendering/Objects/RDShader.cs index 1d30b49..ac9e600 100644 --- a/Runtime/Rendering/Objects/RDShader.cs +++ b/Runtime/Rendering/Objects/RDShader.cs @@ -8,10 +8,38 @@ namespace Rokojori public RDShader( RDContext context, Rid rid ):base( context, rid ) {} - public static RDShader CreateFromSpirV( RDContext context, RDShaderSpirV rDShaderSpirV ) + public static RDShader CreateFromSpirV( RDContext context, RDShaderSpirV rDShaderSpirV, string pathInfo = null ) { var shaderID = context.renderingDevice.ShaderCreateFromSpirV( rDShaderSpirV ); + + if ( ! shaderID.IsValid ) + { + context.Error( "Couldn't create shader from spirV. PathInfo:", pathInfo ); + return null; + } + return new RDShader( context, shaderID ); } + + public static RDShader FromPath( RDContext context, string path ) + { + var glslFile = GD.Load( path ); + + if ( glslFile == null ) + { + context.Error( "File not found:", path ); + return null; + } + + var spirV = glslFile.GetSpirV(); + + if ( spirV == null ) + { + context.Error( "SpirV is null", path ); + return null; + } + + return CreateFromSpirV( context, spirV, path ); + } } } \ No newline at end of file diff --git a/Runtime/Rendering/Objects/RDTexture.cs b/Runtime/Rendering/Objects/RDTexture.cs index d0fd50d..525c2ab 100644 --- a/Runtime/Rendering/Objects/RDTexture.cs +++ b/Runtime/Rendering/Objects/RDTexture.cs @@ -26,6 +26,121 @@ namespace Rokojori return new RDTexture( context, rid ); } + public void SetData( byte[] data, int layer = 0 ) + { + var error = context.renderingDevice.TextureUpdate( rid, (uint) layer, data ); + + if ( error == Error.Ok ) + { + context.Verbose( "Data was set" ); + return; + + } + + context.Error( error ); + } + + public void SetData( Viewport viewport ) + { + SetData( viewport.GetTexture().GetImage() ); + } + + public void SetData( Image image ) + { + var textureDataFormat = RDTextureFormats.ImageFormatToDataFormat( image.GetFormat() ); + + if ( textureDataFormat != format.Format ) + { + context.Error( "Incompatible image format:", textureDataFormat, " Expected:", format.Format ); + return; + } + + SetData( image.GetData() ); + } + + public int numPixels => (int) ( format.Width * format.Height ); + public int channelsPerPixel => RDTextureFormats.GetNumChannels( format.Format ); + + public RDTextureFormats.PixelChannelEncoding pixelChannelEncoding => RDTextureFormats.GetPixelChannelEncoding( format.Format ); + + public int bytesPerPixel => RDTextureFormats.NumBytesFor( pixelChannelEncoding ) * channelsPerPixel; + + public int GetNumBytes( int layer = 0 ) + { + var bytes = numPixels * bytesPerPixel; + + while ( layer > 0 ) + { + bytes /= 4; + layer --; + } + + return bytes; + } + + public void SetData( Color color ) + { + var fmt = format.Format; + + var colorBytes = RDTextureFormats.ColorToBytes( color, fmt ); + + if ( colorBytes == null ) + { + context.Error( "Unsupported texture format" ); + return; + } + + context.Verbose( "ColorBytes:", colorBytes ); + + var bytes = new byte[ GetNumBytes() ]; + + context.Verbose( "NumPixels", numPixels, "BytesPerPixel", bytesPerPixel, "Num Bytes", GetNumBytes( 0 ) ); + + for ( int i = 0; i < bytes.Length; i+= colorBytes.Length ) + { + System.Array.Copy( colorBytes, 0, bytes, i, colorBytes.Length ); + } + + context.Verbose( "First Byte", bytes[ 0 ], bytes[ 1 ], bytes[ 2 ], bytes[ 3 ] ); + + SetData( bytes ); + } + + public byte[] GetData( int layer = 0) + { + return context.renderingDevice.TextureGetData( rid, (uint) layer ); + } + + public int width => (int) format.Width; + public int height => (int) format.Height; + + public RenderingDevice.DataFormat dataFormat => format.Format; + public Image.Format imageFormat => RDTextureFormats.DataFormatToImageFormat( dataFormat ); + + public Image GetImage() + { + var fmt = format; + var imgF = RDTextureFormats.DataFormatToImageFormat( format.Format ); + + + var data = GetData(); + + var output = ""; + for ( int i = 0; i < 20; i++ ) + { + if ( i != 0 ){ output += ", "; } + output += data[ i ] + ""; + } + + context.Verbose( "Converting:", fmt.Format, ">>", imgF, "output:", output ); + return Image.CreateFromData( (int) fmt.Width, (int)fmt.Height, false, imgF, data ); + } + + public Texture2D GetTexture2D() + { + return ImageTexture.CreateFromImage( GetImage() ); + } + public RDTextureFormat format { get @@ -67,7 +182,7 @@ namespace Rokojori return new RDTexture( context, rid ); } - public static RDTextureFormat DefaultFormat( int w, int h, RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Unorm ) + public static RDTextureFormat DefaultFormat( int w, int h, RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Sfloat) { var format = new RDTextureFormat(); @@ -77,60 +192,51 @@ namespace Rokojori format.UsageBits = RenderingDevice.TextureUsageBits.StorageBit | RenderingDevice.TextureUsageBits.SamplingBit | RenderingDevice.TextureUsageBits.CanCopyFromBit | + RenderingDevice.TextureUsageBits.CanUpdateBit | + RenderingDevice.TextureUsageBits.CanCopyToBit | RenderingDevice.TextureUsageBits.CpuReadBit ; return format; } - public static RDTextureFormat FormatChangeSize( RDTextureFormat tf, Vector2I size ) - { - return FormatChangeSize( tf, size.X, size.Y ); - } - - public static RDTextureFormat FormatChangeSize( RDTextureFormat tf, int w, int h ) - { - var clone = FormatCopy( tf ); - clone.Width = (uint) w; - clone.Height = (uint) h; - return clone; - } - - public static RDTextureFormat FormatCopy( RDTextureFormat tf ) - { - var format = new RDTextureFormat(); - - format.Format = tf.Format; - - format.Width = tf.Width; - format.Height = tf.Height; - format.Depth = tf.Depth; - - format.ArrayLayers = tf.ArrayLayers; - format.Mipmaps = tf.Mipmaps; - format.TextureType = tf.TextureType; - format.Samples = tf.Samples; - format.UsageBits = tf.UsageBits; - format.IsResolveBuffer = tf.IsResolveBuffer; - format.IsDiscardable = tf.IsDiscardable; - - return tf; - - } - - public static RDTexture Create( RDContext context, Vector2I size, RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Unorm ) + public static RDTexture Create( RDContext context, Vector2I size, RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Sfloat ) { return Create( context, size.X, size.Y, dataFormat ); - } + } + public static RDTexture Create( RDContext context, int width, int height, - RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Unorm ) + RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Sfloat, + RenderingDevice.TextureUsageBits textureUsageBits = RDTextureFormats.Usage_Default ) { var view = new RDTextureView(); - var format = DefaultFormat( width, height, dataFormat ); + var format = RDTextureFormats.DefaultFormat( width, height, dataFormat ); + format.UsageBits = textureUsageBits; + + context.Verbose( "Format:", format, "DataFormat", dataFormat); var rid = context.renderingDevice.TextureCreate( format, view ); return new RDTexture( context, rid ); } + + + public static RDTexture CreateCopyFrom( RDContext context, SubViewport viewport ) + { + var dataFormat = RDTextureFormats.GetDataFormat( viewport ); + var bytes = RDTextureFormats.GetNumBytes( viewport ); + var image = viewport.GetTexture().GetImage(); + var viewPortImageFormat = image.GetFormat(); + var rdFormat = RDTextureFormats.ImageFormatToDataFormat( viewPortImageFormat ); + var data = image.GetData(); + + RJLog.Log( "Data", data.Length, Lists.SubList( data, 0, 100 ) ); + + RJLog.Log( "Copying Texture From", viewport.Size, viewPortImageFormat, rdFormat, "Bytes", bytes ); + var texture = Create( context, viewport.Size, dataFormat ); + + texture.SetData( data ); + return texture; + } } } \ No newline at end of file diff --git a/Runtime/Rendering/Objects/RDTextureFormats.cs b/Runtime/Rendering/Objects/RDTextureFormats.cs new file mode 100644 index 0000000..bc2226c --- /dev/null +++ b/Runtime/Rendering/Objects/RDTextureFormats.cs @@ -0,0 +1,440 @@ + +using System; +using Godot; +using System.Collections.Generic; +using System.Text; + +namespace Rokojori +{ + public class RDTextureFormats + { + public enum PixelChannelEncoding + { + Unknown, + + uInt8, + sInt8, + + uInt16, + sInt16, + sFloat16, + uNorm16, + sNorm16, + + uInt32, + sInt32, + sFloat32 + } + + public static readonly List bits8 = new List() + { + PixelChannelEncoding.uInt8, + PixelChannelEncoding.sInt8 + }; + + public static readonly List bits32 = new List() + { + PixelChannelEncoding.uInt32, + PixelChannelEncoding.sInt32, + PixelChannelEncoding.sFloat32 + }; + + public static int NumBytesFor( PixelChannelEncoding encoding ) + { + if ( PixelChannelEncoding.Unknown == encoding ) + { + return -1; + } + + if ( bits8.Contains( encoding ) ) + { + return 1; + } + + if ( bits32.Contains( encoding ) ) + { + return 4; + } + + return 2; + } + + public static string UsageInfo( RenderingDevice.TextureUsageBits bits ) + { + var enums = Enum.GetValues(); + + var sb = new StringBuilder(); + var first = true; + + Array.ForEach( enums, + e => + { + if ( ! BitMath.IsMaskSet( (long)bits, (long)e ) ) + { + return; + } + + if ( first ){ first = false; } + else { sb.Append( ", " ); } + + sb.Append( e + "" ); + + } + ); + + return sb.ToString(); + } + + public const RenderingDevice.TextureUsageBits Usage_Default = + RenderingDevice.TextureUsageBits.SamplingBit | + RenderingDevice.TextureUsageBits.StorageBit | + RenderingDevice.TextureUsageBits.CpuReadBit | + RenderingDevice.TextureUsageBits.CanUpdateBit | + RenderingDevice.TextureUsageBits.CanCopyFromBit | + RenderingDevice.TextureUsageBits.CanCopyToBit; + + + public static RDTextureFormat DefaultFormat( int w, int h, RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Unorm ) + { + var format = new RDTextureFormat(); + + format.Width = (uint) w; + format.Height = (uint) h; + format.Format = dataFormat; + format.UsageBits = Usage_Default; + + return format; + } + + public static RDTextureFormat FormatChangeSize( RDTextureFormat tf, Vector2I size ) + { + return FormatChangeSize( tf, size.X, size.Y ); + } + + public static RDTextureFormat FormatChangeSize( RDTextureFormat tf, int w, int h ) + { + var clone = FormatCopy( tf ); + clone.Width = (uint) w; + clone.Height = (uint) h; + return clone; + } + + public static int GetNumPixels( SubViewport viewport ) + { + return viewport.Size.X * viewport.Size.Y; + } + + public static int GetNumBytes( SubViewport viewport ) + { + var numChannels = viewport.TransparentBg ? 4 : 3; + var encoding = viewport.UseHdr2D ? 2 : 1; + + return GetNumPixels( viewport ) * numChannels * encoding; + } + + public static RenderingDevice.DataFormat GetDataFormat( Viewport viewport ) + { + var imageFormat = viewport.GetTexture().GetImage().GetFormat(); + return ImageFormatToDataFormat( imageFormat ); + } + + public static RDTextureFormat FormatCopy( RDTextureFormat tf ) + { + var format = new RDTextureFormat(); + + format.Format = tf.Format; + + format.Width = tf.Width; + format.Height = tf.Height; + format.Depth = tf.Depth; + + format.ArrayLayers = tf.ArrayLayers; + format.Mipmaps = tf.Mipmaps; + format.TextureType = tf.TextureType; + format.Samples = tf.Samples; + format.UsageBits = tf.UsageBits; + format.IsResolveBuffer = tf.IsResolveBuffer; + format.IsDiscardable = tf.IsDiscardable; + + return tf; + + } + + public static RenderingDevice.DataFormat DataFormat( int channels, PixelChannelEncoding encoding ) + { + if ( 1 == channels ) + { + return DataFormat_1Channel( encoding ); + } + + if ( 2 == channels ) + { + return DataFormat_2Channels( encoding ); + } + + if ( 3 == channels ) + { + return DataFormat_3Channels( encoding ); + } + + if ( 4 == channels ) + { + return DataFormat_4Channels( encoding ); + } + + return RenderingDevice.DataFormat.Max; + } + + public static RenderingDevice.DataFormat ImageFormatToDataFormat( Image.Format imageFormat ) + { + RJLog.Log( "ImageFormatToDataFormat", imageFormat ); + + switch ( imageFormat ) + { + case Image.Format.Rgb8: return RenderingDevice.DataFormat.R8G8B8Uint; + case Image.Format.Rgba8: return RenderingDevice.DataFormat.R8G8B8A8Uint; + case Image.Format.Rgbah: return RenderingDevice.DataFormat.R16G16B16A16Sfloat; + } + + return RenderingDevice.DataFormat.Max; + } + + public static Image.Format DataFormatToImageFormat( RenderingDevice.DataFormat dataFormat ) + { + switch ( dataFormat ) + { + case RenderingDevice.DataFormat.R8G8B8A8Uint: return Image.Format.Rgba8; + case RenderingDevice.DataFormat.R8G8B8Uint: return Image.Format.Rgb8; + case RenderingDevice.DataFormat.R16G16B16A16Sfloat: return Image.Format.Rgbah; + } + + return Image.Format.Max; + } + + public static RenderingDevice.DataFormat DataFormat_1Channel( PixelChannelEncoding encoding ) + { + switch ( encoding ) + { + case PixelChannelEncoding.uInt8: return RenderingDevice.DataFormat.R8Uint; + } + + return RenderingDevice.DataFormat.Max; + } + + public static RenderingDevice.DataFormat DataFormat_2Channels( PixelChannelEncoding encoding ) + { + switch ( encoding ) + { + case PixelChannelEncoding.uInt8: return RenderingDevice.DataFormat.R8Uint; + } + + return RenderingDevice.DataFormat.Max; + } + + public static RenderingDevice.DataFormat DataFormat_3Channels( PixelChannelEncoding encoding ) + { + switch ( encoding ) + { + case PixelChannelEncoding.uInt8: return RenderingDevice.DataFormat.R8G8B8Uint; + case PixelChannelEncoding.sInt8: return RenderingDevice.DataFormat.R8G8B8Sint; + + case PixelChannelEncoding.uInt16: return RenderingDevice.DataFormat.R16G16B16Uint; + case PixelChannelEncoding.sInt16: return RenderingDevice.DataFormat.R16G16B16Sint; + case PixelChannelEncoding.sFloat16: return RenderingDevice.DataFormat.R16G16B16Sfloat; + case PixelChannelEncoding.uNorm16: return RenderingDevice.DataFormat.R16G16B16Unorm; + case PixelChannelEncoding.sNorm16: return RenderingDevice.DataFormat.R16G16B16Snorm; + + case PixelChannelEncoding.uInt32: return RenderingDevice.DataFormat.R32G32B32Uint; + case PixelChannelEncoding.sInt32: return RenderingDevice.DataFormat.R32G32B32Sint; + case PixelChannelEncoding.sFloat32: return RenderingDevice.DataFormat.R32G32B32Sfloat; + + } + + return RenderingDevice.DataFormat.Max; + } + + + + + public static RenderingDevice.DataFormat DataFormat_4Channels( PixelChannelEncoding encoding ) + { + switch ( encoding ) + { + + case PixelChannelEncoding.uInt8: return RenderingDevice.DataFormat.R8G8B8A8Uint; + case PixelChannelEncoding.sInt8: return RenderingDevice.DataFormat.R8G8B8A8Sint; + + case PixelChannelEncoding.uInt16: return RenderingDevice.DataFormat.R16G16B16A16Uint; + case PixelChannelEncoding.sInt16: return RenderingDevice.DataFormat.R16G16B16A16Sint; + case PixelChannelEncoding.sFloat16: return RenderingDevice.DataFormat.R16G16B16A16Sfloat; + case PixelChannelEncoding.uNorm16: return RenderingDevice.DataFormat.R16G16B16A16Unorm; + case PixelChannelEncoding.sNorm16: return RenderingDevice.DataFormat.R16G16B16A16Snorm; + + case PixelChannelEncoding.uInt32: return RenderingDevice.DataFormat.R32G32B32A32Uint; + case PixelChannelEncoding.sInt32: return RenderingDevice.DataFormat.R32G32B32A32Sint; + case PixelChannelEncoding.sFloat32: return RenderingDevice.DataFormat.R32G32B32A32Sfloat; + + } + + return RenderingDevice.DataFormat.Max; + } + + // m: case ((?:\w|\.)*): return ((?:\w|\.)*); + // r: case $2: return $1; + + public static PixelChannelEncoding GetPixelChannelEncoding( RenderingDevice.DataFormat format ) + { + switch ( format ) + { + case RenderingDevice.DataFormat.R8G8B8Sint: return PixelChannelEncoding.sInt8; + + case RenderingDevice.DataFormat.R16G16B16Uint: return PixelChannelEncoding.uInt16; + case RenderingDevice.DataFormat.R16G16B16Sint: return PixelChannelEncoding.sInt16; + case RenderingDevice.DataFormat.R16G16B16Sfloat: return PixelChannelEncoding.sFloat16; + case RenderingDevice.DataFormat.R16G16B16Unorm: return PixelChannelEncoding.uNorm16; + case RenderingDevice.DataFormat.R16G16B16Snorm: return PixelChannelEncoding.sNorm16; + + case RenderingDevice.DataFormat.R32G32B32Uint: return PixelChannelEncoding.uInt32; + case RenderingDevice.DataFormat.R32G32B32Sint: return PixelChannelEncoding.sInt32; + case RenderingDevice.DataFormat.R32G32B32Sfloat: return PixelChannelEncoding.sFloat32; + + case RenderingDevice.DataFormat.R8G8B8A8Uint: return PixelChannelEncoding.uInt8; + case RenderingDevice.DataFormat.R8G8B8A8Sint: return PixelChannelEncoding.sInt8; + + case RenderingDevice.DataFormat.R16G16B16A16Uint: return PixelChannelEncoding.uInt16; + case RenderingDevice.DataFormat.R16G16B16A16Sint: return PixelChannelEncoding.sInt16; + case RenderingDevice.DataFormat.R16G16B16A16Sfloat: return PixelChannelEncoding.sFloat16; + case RenderingDevice.DataFormat.R16G16B16A16Unorm: return PixelChannelEncoding.uNorm16; + case RenderingDevice.DataFormat.R16G16B16A16Snorm: return PixelChannelEncoding.sNorm16; + + case RenderingDevice.DataFormat.R32G32B32A32Uint: return PixelChannelEncoding.uInt32; + case RenderingDevice.DataFormat.R32G32B32A32Sint: return PixelChannelEncoding.sInt32; + case RenderingDevice.DataFormat.R32G32B32A32Sfloat: return PixelChannelEncoding.sFloat32; + } + + return PixelChannelEncoding.Unknown; + } + + public static int GetNumChannels( RenderingDevice.DataFormat format ) + { + switch ( format ) + { + case RenderingDevice.DataFormat.R8G8B8Sint: + + case RenderingDevice.DataFormat.R16G16B16Uint: + case RenderingDevice.DataFormat.R16G16B16Sint: + case RenderingDevice.DataFormat.R16G16B16Sfloat: + case RenderingDevice.DataFormat.R16G16B16Unorm: + case RenderingDevice.DataFormat.R16G16B16Snorm: + + case RenderingDevice.DataFormat.R32G32B32Uint: + case RenderingDevice.DataFormat.R32G32B32Sint: + case RenderingDevice.DataFormat.R32G32B32Sfloat: + + return 3; + + case RenderingDevice.DataFormat.R8G8B8A8Uint: + case RenderingDevice.DataFormat.R8G8B8A8Sint: + + case RenderingDevice.DataFormat.R16G16B16A16Uint: + case RenderingDevice.DataFormat.R16G16B16A16Sint: + case RenderingDevice.DataFormat.R16G16B16A16Sfloat: + case RenderingDevice.DataFormat.R16G16B16A16Unorm: + case RenderingDevice.DataFormat.R16G16B16A16Snorm: + + case RenderingDevice.DataFormat.R32G32B32A32Uint: + case RenderingDevice.DataFormat.R32G32B32A32Sint: + case RenderingDevice.DataFormat.R32G32B32A32Sfloat: + return 4; + } + + return -1; + } + + static void WriteUShort( ushort shortValue, byte[] output, int offset ) + { + output[ offset + 0 ] = (byte)(shortValue & 0xFF); + output[ offset + 1 ] = (byte)((shortValue >> 8) & 0xFF); + } + + static void WriteUNorm( float value, byte[] output, int offset ) + { + var shortValue = (ushort)( Mathf.Clamp( value, 0.0f, 1.0f ) * 65535 ); + WriteUShort( shortValue, output, offset ); + } + + static ushort FloatToHalf( float value ) + { + uint fbits = BitConverter.SingleToUInt32Bits(value); + + uint sign = (fbits >> 16) & 0x8000; + uint val = (fbits & 0x7FFFFFFF); + + // NaN / Inf -> maximal darstellen + if ( val > 0x47FFEFFF ) + { + return (ushort)(sign | 0x7FFF); + } + + if ( val < 0x38800000) // Subnormal + { + uint mant = (val & 0x007FFFFF) | 0x00800000; + int exp = 113 - (int)(val >> 23); + mant = (mant >> exp); + + return (ushort)(sign | (mant >> 13)); + } + else + { + uint exp = (val >> 23) - 112; + uint mant = (val & 0x007FFFFF); + return (ushort)(sign | (exp << 10) | (mant >> 13)); + } + } + + static void WriteFloat16( float value, byte[] output, int offset ) + { + ushort r = FloatToHalf( value ); + WriteUShort( r, output, offset ); + } + + public static byte[] ColorToBytes( Color color, RenderingDevice.DataFormat format ) + { + switch ( format ) + { + case RenderingDevice.DataFormat.R8G8B8A8Uint: + { + var bytes = new byte[ 4 ]; + bytes[ 0 ] = (byte) ( color.R * 255 ); + bytes[ 1 ] = (byte) ( color.G * 255 ); + bytes[ 2 ] = (byte) ( color.B * 255 ); + bytes[ 3 ] = (byte) ( color.A * 255 ); + return bytes; + } + + case RenderingDevice.DataFormat.R16G16B16A16Unorm: + { + var bytes = new byte[ 8 ]; + WriteUNorm( color.R, bytes, 0 ); + WriteUNorm( color.G, bytes, 2 ); + WriteUNorm( color.B, bytes, 4 ); + WriteUNorm( color.A, bytes, 6 ); + return bytes; + } + + case RenderingDevice.DataFormat.R16G16B16A16Sfloat: + { + var bytes = new byte[ 8 ]; + WriteFloat16( color.R, bytes, 0 ); + WriteFloat16( color.G, bytes, 2 ); + WriteFloat16( color.B, bytes, 4 ); + WriteFloat16( color.A, bytes, 6 ); + return bytes; + } + + } + + return null; + } + } +} \ No newline at end of file diff --git a/Runtime/Rendering/Objects/RDTextureFormats.cs.uid b/Runtime/Rendering/Objects/RDTextureFormats.cs.uid new file mode 100644 index 0000000..116d57a --- /dev/null +++ b/Runtime/Rendering/Objects/RDTextureFormats.cs.uid @@ -0,0 +1 @@ +uid://bwinqvkypbchr diff --git a/Runtime/Rendering/Objects/RDUniformSet.cs b/Runtime/Rendering/Objects/RDUniformSet.cs index 1d44dec..8305132 100644 --- a/Runtime/Rendering/Objects/RDUniformSet.cs +++ b/Runtime/Rendering/Objects/RDUniformSet.cs @@ -21,8 +21,9 @@ namespace Rokojori uniform.Binding = 0; uniform.AddId( texture.rid ); - var rd = context.renderingDevice; - var rid = UniformSetCacheRD.GetCache( context.shader.rid, (uint) setIndex, new Array { uniform } ); + + var rid = context._CreateUniformSetRid( setIndex, uniform ); + // UniformSetCacheRD.GetCache( context.shader.rid, (uint) setIndex, new Array { uniform } ); // var rid = rd.UniformSetCreate( new Array{ uniform }, effect.context.shader.rid, (uint) setIndex ); return new RDUniformSet( context, setIndex, rid ); @@ -35,10 +36,9 @@ namespace Rokojori uniform.Binding = 0; uniform.AddId( sampler.rid ); uniform.AddId( texture.rid ) ; - - var rd = context.renderingDevice; - var rid = UniformSetCacheRD.GetCache( context.shader.rid, (uint) setIndex, new Array{ uniform } ); + // var rid = UniformSetCacheRD.GetCache( context.shader.rid, (uint) setIndex, new Array{ uniform } ); + var rid = context._CreateUniformSetRid( setIndex, uniform ); // var rid = rd.UniformSetCreate( new Array{ uniform }, effect.context.shader.rid, (uint) setIndex ); return new RDUniformSet( context, setIndex, rid ); diff --git a/Runtime/Rendering/Objects/RenderingObject.cs b/Runtime/Rendering/Objects/RenderingObject.cs index 9162766..ae0b137 100644 --- a/Runtime/Rendering/Objects/RenderingObject.cs +++ b/Runtime/Rendering/Objects/RenderingObject.cs @@ -17,6 +17,10 @@ namespace Rokojori { this._context = context; this._rid = rid; + + this._context.AddToCleanUp( this, GetType().Name + "@" + _rid ); + + context.Verbose( "Creating", GetType().Name, rid ); } } diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/AlphaColorDilation.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/AlphaColorDilation.glsl new file mode 100644 index 0000000..caab896 --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/AlphaColorDilation.glsl @@ -0,0 +1,93 @@ +#[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; + + +void main( ) +{ + float treshold = 0.5; + + ivec2 size = imageSize( inputImage ); + ivec2 texelCoord = ivec2( gl_GlobalInvocationID.xy ); + + if ( any( greaterThanEqual( texelCoord, size ) ) ) + { + return; + } + + vec4 color = imageLoad( inputImage, texelCoord ); + + // color = vec4( 1.0, 0.0, 0.0, 0.0 ); + + if ( color.a >= treshold ) + { + imageStore( outputImage, texelCoord, color ); + return; + } + // else + // { + // imageStore( outputImage, texelCoord, vec4(1,1,1,1) ); + // return; + // } + + // if ( color.a <= treshold ) + // { + // color = vec4( 1.0, 0.5, color.a, 1.0 ); + // } + // else + // { + // color = vec4( 0.0, 1.0, 0.0, 1.0 ); + // } + + // imageStore( outputImage, texelCoord, color ); + + // imageStore( outputImage, texel_coord, vec4( color.a, color.a, color.a, 1.0 ) ); + + int kernelRadius = 16; + + float closestDistance = kernelRadius * kernelRadius * 2; + vec4 closestColor = color; + + for ( int x = -kernelRadius; x <= kernelRadius; x++ ) + { + for ( int y = -kernelRadius; y <= kernelRadius; y++ ) + { + ivec2 offset = ivec2( x, y ); + float d = length( vec2( offset ) ); + + if ( d >= closestDistance ) + { + continue; + } + + ivec2 t = texelCoord + ivec2( x, y ); + + if ( t.x < 0 || t.y < 0 || ( any( greaterThanEqual( texelCoord, size ) ) ) ) + { + continue; + } + + vec4 nColor = imageLoad( inputImage, t ); + + if ( nColor.a < treshold ) + { + continue; + } + + closestDistance = d; + closestColor = nColor; + + + } + } + + imageStore( outputImage, texelCoord, vec4( closestColor.rgb, color.a ) ); + +} \ No newline at end of file diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/AlphaColorDilation.glsl.import b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/AlphaColorDilation.glsl.import new file mode 100644 index 0000000..ec72730 --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/AlphaColorDilation.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://byc7b6xlw0fnj" +path="res://.godot/imported/AlphaColorDilation.glsl-7665d7fc960d5dbc00617ba2dd53045f.res" + +[deps] + +source_file="res://addons/rokojori_action_library/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/AlphaColorDilation.glsl" +dest_files=["res://.godot/imported/AlphaColorDilation.glsl-7665d7fc960d5dbc00617ba2dd53045f.res"] + +[params] + diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/CEG_AlphaColorDilation.cs b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/CEG_AlphaColorDilation.cs new file mode 100644 index 0000000..4fc758f --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/CEG_AlphaColorDilation.cs @@ -0,0 +1,17 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + public class CEG_AlphaColorDilation:CEG_ImageProcessor + { + public static readonly string shaderPath = + RDGraph.Path( "Nodes/Processors/Color/AlphaColorDilation/AlphaColorDilation.glsl" ); + + public CEG_AlphaColorDilation( RDGraph graph ):base( graph, shaderPath ) + {} + + + } +} \ No newline at end of file diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/CEG_AlphaColorDilation.cs.uid b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/CEG_AlphaColorDilation.cs.uid new file mode 100644 index 0000000..7865dc6 --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/AlphaColorDilation/CEG_AlphaColorDilation.cs.uid @@ -0,0 +1 @@ +uid://daimt0g1aluu4 diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/ChromaticAberation/ChromaticAberation.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/ChromaticAberation/ChromaticAberation.glsl index 23e9df0..da662a2 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/ChromaticAberation/ChromaticAberation.glsl +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Color/ChromaticAberation/ChromaticAberation.glsl @@ -12,12 +12,12 @@ uniform image2D outputImage; layout( push_constant, std430 ) uniform Params { - float amount; - float shiftAll; - float unshiftCenter; vec2 rShift; vec2 gShift; vec2 bShift; + float amount; + float shiftAll; + float unshiftCenter; } params; diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Copy/Copy.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/Copy/Copy.glsl index 0fe9a57..4c1e2b8 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/Copy/Copy.glsl +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Copy/Copy.glsl @@ -11,8 +11,15 @@ uniform restrict writeonly image2D outputImage; void main() { + ivec2 imgSize = imageSize( inputImage ); ivec2 currentPosition = ivec2( gl_GlobalInvocationID.xy ); - vec4 currentPixel = imageLoad( inputImage, currentPosition ); - + + if ( any( greaterThanEqual( currentPosition, imgSize ) ) ) + { + return; + } + + vec4 currentPixel = imageLoad( inputImage, currentPosition ); + imageStore( outputImage, currentPosition, currentPixel ); } diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_BufferTexture.cs b/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_BufferTexture.cs index 001bdf9..24a4a24 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_BufferTexture.cs +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/Generic/CEG_BufferTexture.cs @@ -37,7 +37,7 @@ namespace Rokojori if ( texture == null || scaledSize != texture.size ) { AutoClean( texture, graph.context.renderingDevice ); - format = RDTexture.FormatChangeSize( format, scaledSize ); + format = RDTextureFormats.FormatChangeSize( format, scaledSize ); texture = RDTexture.Create( graph.context, format ); } @@ -63,6 +63,20 @@ namespace Rokojori } } + public class CEG_TextureCreator_Reference:CEG_TextureCreator + { + public RDTexture _texture; + + public CEG_TextureCreator_Reference( RDTexture texture ) + { + this._texture = texture; + } + + public override RDTexture Create( RDTexture texture, RDGraph graph ) + { + return _texture; + } + } public class CEG_BufferTexture:RGGraphProcessor, RDGraphTextureSlotInput @@ -106,6 +120,20 @@ namespace Rokojori return new CEG_BufferTexture( graph, new CEG_TextureCreator_FixedSize() ); } + public static CEG_BufferTexture FixedSize( RDGraph graph, Vector2I size ) + { + var creator = new CEG_TextureCreator_FixedSize(); + creator.format.Width = (uint) size.X; + creator.format.Height = (uint) size.Y; + return new CEG_BufferTexture( graph, creator ); + } + + public static CEG_BufferTexture From( RDGraph graph, RDTexture texture ) + { + var creator = new CEG_TextureCreator_Reference( texture ); + return new CEG_BufferTexture( graph, creator ); + } + public override void Process() { _texture = _creator.Create( _texture, graph ); diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/CEG_JFAAssign.cs b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/CEG_JFAAssign.cs new file mode 100644 index 0000000..3ad66a3 --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/CEG_JFAAssign.cs @@ -0,0 +1,17 @@ + +using Godot; +using System.Collections.Generic; + +namespace Rokojori +{ + public class CEG_JFAAssign:CEG_ImageProcessor + { + public static readonly string shaderPath = + RDGraph.Path( "Nodes/Processors/JFA/JFA_Assign.glsl" ); + + public CEG_JFAAssign( RDGraph graph ):base( graph, shaderPath ) + {} + + + } +} \ No newline at end of file diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl new file mode 100644 index 0000000..7bc0aaf --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl @@ -0,0 +1,24 @@ +#[compute] +#version 450 + +layout( local_size_x = 8, local_size_y = 8, local_size_z = 1 ) in; + +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() +{ + ivec2 currentPosition = ivec2( gl_GlobalInvocationID.xy ); + vec4 currentPixel = imageLoad( inputImage, currentPosition ); + ivec2 seedPosition = ivec2( packUnorm2x16( currentPixel.xy ), packUnorm2x16( currentPixel.zw ) ); + + vec4 originalPixel = imageLoad( originalImage, seedPosition ); + + imageStore(outputImage, currentPosition, vec4(originalPixel.xyz, originalPixel.a)); +} diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl.import b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl.import new file mode 100644 index 0000000..d37b0d6 --- /dev/null +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://1ovj3jsq1vp6" +path="res://.godot/imported/JFA_Assign.glsl-fb7dfb3a0e8b719d928d34ea126deab2.res" + +[deps] + +source_file="res://addons/rokojori_action_library/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Assign.glsl" +dest_files=["res://.godot/imported/JFA_Assign.glsl-fb7dfb3a0e8b719d928d34ea126deab2.res"] + +[params] + diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Initialize.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Initialize.glsl index 99e07d9..4338f23 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Initialize.glsl +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Initialize.glsl @@ -10,18 +10,18 @@ layout( rgba16, set = 1, binding = 0 ) uniform restrict writeonly image2D outputImage; layout( push_constant, std430 ) -uniform Params +uniform Parameters { float alphaTreshold; -} params; +} parameters; void main() { ivec2 currentPosition = ivec2( gl_GlobalInvocationID.xy ); vec4 currentPixel = imageLoad( inputImage, currentPosition ); - if ( currentPixel.a < params.alphaTreshold ) + if ( currentPixel.a < parameters.alphaTreshold ) { vec4 packedZero = vec4( unpackUnorm2x16( 0 ), unpackUnorm2x16( 0 ) ); imageStore( outputImage, currentPosition, packedZero ); diff --git a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Iterate.glsl b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Iterate.glsl index 682600c..de274a7 100644 --- a/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Iterate.glsl +++ b/Runtime/Rendering/RenderGraph/Nodes/Processors/JFA/JFA_Iterate.glsl @@ -10,7 +10,11 @@ layout(rgba16, set = 1, binding = 0) uniform restrict writeonly image2D outputImage; layout(std430, set = 2, binding = 0) -buffer restrict readonly JumpDistanceBuffer { int jump; } jdb; +buffer restrict readonly DistanceParameters +{ + int jump; + +} distanceParameters; void main() { @@ -20,7 +24,7 @@ void main() float distanceToClosestSeed = 1.0f / 0.0f; vec4 closestSeed = vec4( unpackUnorm2x16( 0 ), unpackUnorm2x16( 0 ) ); - ivec2 jdbJump = ivec2( jdb.jump, jdb.jump ); + ivec2 jump = ivec2( distanceParameters.jump, distanceParameters.jump ); for ( int x = -1; x <= 1; x++ ) { @@ -28,7 +32,7 @@ void main() { ivec2 xy = ivec2( x, y ); - ivec2 checkPosition = currentPosition + jdbJump * xy; + ivec2 checkPosition = currentPosition + jump * xy; if ( checkPosition.x < 0 || checkPosition.y < 0 || checkPosition.x >= imageSize.x || checkPosition.y >= imageSize.y ) diff --git a/Runtime/Rendering/RenderGraph/RDShaderProcessor.cs b/Runtime/Rendering/RenderGraph/RDShaderProcessor.cs index 016603e..ccd1920 100644 --- a/Runtime/Rendering/RenderGraph/RDShaderProcessor.cs +++ b/Runtime/Rendering/RenderGraph/RDShaderProcessor.cs @@ -62,7 +62,7 @@ namespace Rokojori var context = graph.context; context.Clear(); - context.CalculateComputeGroups( _groupSize ); + context.CalculateSceneComputeGroups( _groupSize ); context.SetShaderAndPipeline( _shader, _pipeline ); _textureSlots.ForEach( t => diff --git a/Runtime/Tools/Lists.cs b/Runtime/Tools/Lists.cs index 8019fb4..1a6498a 100644 --- a/Runtime/Tools/Lists.cs +++ b/Runtime/Tools/Lists.cs @@ -10,6 +10,7 @@ namespace Rokojori public static class Lists { + public static bool IsOneOf( T value, params T[] values ) { for ( int i = 0; i < values.Length; i++ ) @@ -237,6 +238,18 @@ namespace Rokojori public static List From( params T[] elements ) { return ToList( elements ); + } + + public static List SubList( T[] elements, int offset, int length ) + { + var list = new List(); + + for ( int i = 0; i < length; i++ ) + { + list.Add( elements[ i + offset ] ); + } + + return list; } public static List ToList( T[] array )