JFA Texture Dilation Working
This commit is contained in:
parent
66d24be2c1
commit
7b68cc7f1f
|
@ -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 );
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
this.LogInfo( "Copying texture" );
|
||||
var data = inputTexture.GetData();
|
||||
|
||||
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 ) );
|
||||
|
||||
|
@ -93,9 +109,6 @@ namespace Rokojori
|
|||
await this.RequestNextFrame();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
RDGraph CreateGraph( RDContext ctx, RDTexture it, RDTexture ot )
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<TextureDilate>( "Texture Dilate" );
|
||||
X_textureDilate.viewport = X_textureMerger.X_textureMergerViewport;
|
||||
|
||||
X_outputMesh = this.CreateChild<MeshInstance3D>( "Output Mesh" );
|
||||
|
||||
X_texturePreview = this.CreateChild<MeshInstance3D>( "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 ] );
|
||||
|
|
|
@ -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<Texture2D> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://bfiqjmyt04ils
|
|
@ -122,6 +122,7 @@ namespace Rokojori
|
|||
X_textureMergerViewport.Size = (Vector2I) textureSize;
|
||||
X_textureMergerViewport.OwnWorld3D = true;
|
||||
X_textureMergerViewport.TransparentBg = true;
|
||||
X_textureMergerViewport.UseHdr2D = true;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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,7 +73,24 @@ 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 )
|
||||
{
|
||||
if ( srgbConversion != 0 )
|
||||
{
|
||||
var gamma = Mathf.Pow( 2.2f, srgbConversion );
|
||||
|
||||
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 );
|
||||
sourcePixel = sourcePixel.Gamma( gamma );
|
||||
SetAt( ownX + i, ownY + j, sourcePixel );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for ( int i = 0; i < w; i++ )
|
||||
|
@ -81,12 +98,12 @@ namespace Rokojori
|
|||
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 );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void CopyTo( int ownX, int ownY, int targetX, int targetY, int w, int h, TextureCombinerBuffer output )
|
||||
|
|
|
@ -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<RD_BoxBlur> _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<RD_BoxBlur>()
|
||||
{
|
||||
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<RGGraphProcessor>
|
||||
{
|
||||
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 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://dqsxgtt4e6vwu
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,19 @@ 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 )
|
||||
{
|
||||
|
@ -263,6 +276,7 @@ namespace Rokojori
|
|||
|
||||
if ( pushConstants != null )
|
||||
{
|
||||
Verbose( "Set constants", pushConstants.size );
|
||||
computeList.SetPushConstants( pushConstants );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
|
@ -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]
|
||||
|
|
@ -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 )
|
||||
{}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://b1vkp54fq4kt7
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://6scrdbsfh3vj
|
|
@ -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;
|
||||
uniform restrict writeonly image2D outputImage;
|
||||
|
||||
layout( rgba16, set = 2, binding = 0 )
|
||||
uniform restrict writeonly image2D outputImage;
|
||||
uniform restrict readonly image2D originalImage;
|
||||
|
||||
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 );
|
||||
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) );
|
||||
}
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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<int> onPreProcess;
|
||||
public System.Action<int> 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://bmpqy38ty2nlx
|
|
@ -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" );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue