JFA Texture Dilation Working

This commit is contained in:
Josef 2025-04-30 22:18:22 +02:00
parent 66d24be2c1
commit 7b68cc7f1f
30 changed files with 762 additions and 68 deletions

View File

@ -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 );

View File

@ -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 ) );
}

View File

@ -21,6 +21,21 @@ namespace Rokojori
[Export]
public MeshInstance3D meshInstance3D;
[Export( PropertyHint.Range, "0,1" ) ]
public float intensity;
[Export( PropertyHint.Range, "0,100" ) ]
public float noise;
[Export( PropertyHint.Range, "1,100" ) ]
public float kernelOffset;
[Export( PropertyHint.Range, "1,50" ) ]
public float kernelRadius;
[ExportToolButton( "Grab Texture")]
public Callable GrabButton => Callable.From(
@ -41,9 +56,6 @@ namespace Rokojori
viewport.RenderTargetUpdateMode = updateMode;
}
var viewPortFormat = RDTextureFormats.GetDataFormat( viewport );
var viewPortData = viewport.GetTexture().GetImage().GetData();
var viewPortSize = viewport.Size;
@ -63,23 +75,27 @@ namespace Rokojori
var inputTexture = RDTexture.Create( ctx, viewport.Size, viewPortFormat );
inputTexture.SetData( viewPortData );
this.LogInfo( "Creating graph" );
var graph = CreateGraph( ctx, inputTexture, outputTexture );
this.LogInfo( "Process graph" );
graph.ProcessForView();
ctx.SubmitAndSync();
var width = outputTexture.width;
var height = outputTexture.height;
var format = outputTexture.imageFormat;
var width = inputTexture.width;
var height = inputTexture.height;
var format = inputTexture.imageFormat;
var data = outputTexture.GetData();
var data = inputTexture.GetData();
this.LogInfo( "Copying texture" );
ctx.SubmitAndSync();
await this.RequestNextFrame();
this.LogInfo( "Copying texture" );
var image = Image.CreateFromData( width, height, false, format, data );
var buffer = TextureCombinerBuffer.From( ImageTexture.CreateFromImage( image ) );
@ -92,9 +108,6 @@ namespace Rokojori
await this.RequestNextFrame();
}
@ -106,27 +119,27 @@ namespace Rokojori
var bufferTexture = CEG_BufferTexture.From( graph, ot );
var copy = new CEG_Copy( graph );
var radialBlur = new CEG_RadialBlur( graph );
var blur = new RD_BoxBlur( graph );
graph.InitializeNodes();
copy.SetTextureSlotInputs( viewTexture, bufferTexture );
radialBlur.SetTextureSlotInputs( copy.output, copy.input );
blur.SetTextureSlotInputs( copy.output, copy.input );
graph.SetProcessOrder(
viewTexture, bufferTexture,
copy, radialBlur
copy, blur
);
radialBlur.constants.Set(
new Vector2( 0.5f, 0.5f ),
0.5f,
0.5f,
16,
Vector2.Zero
blur.constants.Set(
intensity,
noise,
kernelOffset,
kernelRadius
);
ctx.Verbose( "Radial Blur constants:", blur.constants.size );
return graph;
}

View File

@ -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 ] );

View File

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

View File

@ -0,0 +1 @@
uid://bfiqjmyt04ils

View File

@ -122,6 +122,7 @@ namespace Rokojori
X_textureMergerViewport.Size = (Vector2I) textureSize;
X_textureMergerViewport.OwnWorld3D = true;
X_textureMergerViewport.TransparentBg = true;
X_textureMergerViewport.UseHdr2D = true;
}

View File

@ -37,10 +37,10 @@ namespace Rokojori
}
}
public static TextureCombinerBuffer From( Texture2D texture )
public static TextureCombinerBuffer From( Texture2D texture, int srgbConversion = 0)
{
var buffer = Create( texture.GetWidth(), texture.GetHeight() );
buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight() );
buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight(), srgbConversion );
return buffer;
}
@ -73,17 +73,34 @@ namespace Rokojori
}
public void CopyFrom( Image image, int sourceX, int sourceY, int ownX, int ownY, int w, int h )
public void CopyFrom( Image image, int sourceX, int sourceY, int ownX, int ownY, int w, int h, int srgbConversion = 0 )
{
for ( int i = 0; i < w; i++ )
if ( srgbConversion != 0 )
{
for ( int j = 0; j < h; j++ )
var gamma = Mathf.Pow( 2.2f, srgbConversion );
for ( int i = 0; i < w; i++ )
{
var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j );
for ( int j = 0; j < h; j++ )
{
var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j );
sourcePixel = sourcePixel.Gamma( gamma );
SetAt( ownX + i, ownY + j, sourcePixel );
SetAt( ownX + i, ownY + j, sourcePixel );
}
}
}
else
{
for ( int i = 0; i < w; i++ )
{
for ( int j = 0; j < h; j++ )
{
var sourcePixel = image == null ? new Color( 0, 0, 0 ) : image.GetPixel( sourceX + i, sourceY + j );
SetAt( ownX + i, ownY + j, sourcePixel );
}
}
}
}

View File

@ -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 );
}
}
}

View File

@ -0,0 +1 @@
uid://dqsxgtt4e6vwu

View File

@ -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 );
}
}

View File

@ -107,12 +107,25 @@ namespace Rokojori
AssignTexture( GetScreenDepthTexture(), sampler, setIndex );
}
RDTexture _missingTexture = null;
Vector2I _missingTextureSize = new Vector2I( 64, 64 );
public void AssignMissingTexture( RDSampler sampler = null, int setIndex = -1 )
{
if ( _missingTexture == null )
{
_missingTexture = RDTexture.Create( this, _missingTextureSize, RenderingDevice.DataFormat.R16G16B16A16Sfloat );
_missingTexture.SetData( new Color( 1, 0, 1, 1 ) );
}
AssignTexture( _missingTexture, sampler, setIndex );
}
public void AssignTexture( RDTexture texture, RDSampler sampler = null, int setIndex = -1 )
{
// effect.Verbose( "Incoming Uniform Index", setIndex );
if ( setIndex == -1 )
if ( setIndex == -1 )
{
setIndex = _uniformSets.Count;
}
@ -263,6 +276,7 @@ namespace Rokojori
if ( pushConstants != null )
{
Verbose( "Set constants", pushConstants.size );
computeList.SetPushConstants( pushConstants );
}

View File

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

View File

@ -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 );

View File

@ -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 );
}

View File

@ -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]

View File

@ -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 )
{}
}
}

View File

@ -0,0 +1 @@
uid://b1vkp54fq4kt7

View File

@ -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()

View File

@ -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()

View File

@ -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 );
}
}
}

View File

@ -0,0 +1 @@
uid://6scrdbsfh3vj

View File

@ -7,18 +7,22 @@ layout( rgba16, set = 0, binding = 0 )
uniform restrict readonly image2D inputImage;
layout( rgba16, set = 1, binding = 0 )
uniform restrict readonly image2D originalImage;
layout( rgba16, set = 2, binding = 0 )
uniform restrict writeonly image2D outputImage;
void main()
{
layout( rgba16, set = 2, binding = 0 )
uniform restrict readonly image2D originalImage;
void main()
{
ivec2 currentPosition = ivec2( gl_GlobalInvocationID.xy );
vec4 currentPixel = imageLoad( inputImage, currentPosition );
vec4 currentPixel = imageLoad( inputImage, currentPosition );
ivec2 seedPosition = ivec2( packUnorm2x16( currentPixel.xy ), packUnorm2x16( currentPixel.zw ) );
vec4 originalPixel = imageLoad( originalImage, seedPosition );
vec4 colorPixel = imageLoad( originalImage, seedPosition );
vec4 originalPixel = imageLoad( originalImage, currentPosition );
imageStore(outputImage, currentPosition, vec4(originalPixel.xyz, originalPixel.a));
vec2 seedUV = vec2( seedPosition ) / imageSize( inputImage );
imageStore( outputImage, currentPosition, vec4( colorPixel.rgb, originalPixel.a) );
}

View File

@ -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 ) );
}

View File

@ -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 );

View File

@ -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();
}
}
}
}

View File

@ -0,0 +1 @@
uid://bmpqy38ty2nlx

View File

@ -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" );
}
}
}

View File

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

View File

@ -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();
}
}