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; [Export] public bool useSRGB = true; [ExportToolButton( "Grab Texture")] public Callable GrabButton => Callable.From( () => { Grab( useSRGB, true ); } ); public void SetDilationRadius( int pixelSize ) { steps = ( Mathf.RoundToInt( MathX.Exponent( 2, pixelSize ) ) - 1 ); } public void SetDilationRadius( Vector2 size ) { SetDilationRadius( Mathf.RoundToInt( Mathf.Max( size.X, size.Y ) ) ); } public async Task Grab( bool srgb, bool alpha, bool mipmaps = false ) { 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 && srgb ) { gammaConversion = -1; } var buffer = TextureCombinerBuffer.From( ImageTexture.CreateFromImage( image ), gammaConversion ); var texture = buffer.CreateImageTexture( alpha, mipmaps ); 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.95f ); 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 ) ); 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; } } }