rj-action-library/Runtime/Procedural/Baking/TextureDilate.cs

196 lines
5.4 KiB
C#

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<Texture2D> 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;
}
}
}