Editor/ShaderGraphPlus/Nodes/Effects/PixelPlot.cs
namespace ShaderGraphPlus.Nodes;
/// <summary>
///
/// </summary>
[Title( "Pixel Plot" ), Category( "Effects" ), Icon( "grid_on" )]
public sealed class PixelPlotNode : ShaderNodePlus
{
[JsonIgnore, Hide, Browsable( false )]
public override Color NodeTitleColor => ShaderGraphPlusTheme.NodeHeaderColors.FunctionNode;
[Hide]
public string PixelPlot => @"
float4 PixelPlot( in Texture2D vColorTex, in SamplerState sSampler, float2 vUv , float2 vGridSize , float flBoarderThickness)
{
float2 vGridBlock = 1.0f / vGridSize;
float2 vUvGrid = floor( vUv * vGridSize ) / vGridSize; // Divide By Gridsize so that uvspace is clamped to 0 to 1.
float2 vGridBoarder = step( 0.5f - flBoarderThickness, frac( vUv / vGridBlock ) ) *
step( frac( vUv / vGridBlock ), 0.5f + flBoarderThickness );
return vColorTex.Sample( sSampler, vUvGrid ) * ( vGridBoarder.x * vGridBoarder.y );
}
";
/// <summary>
/// Texture object to apply the effect to.
/// </summary>
[Title( "Texture2D" )]
[Input( typeof( Texture ) )]
[Hide]
public NodeInput Texture2D { get; set; }
/// <summary>
/// Coordinates to sample this texture
/// </summary>
[Title( "Coordinates" )]
[Input( typeof( Vector2 ) )]
[Hide]
public NodeInput Coords { get; set; }
/// <summary>
/// How the effect is filtered and wrapped when sampled
/// </summary>
[Title( "Sampler" )]
[Input( typeof( Sampler ) )]
[Hide]
public NodeInput Sampler { get; set; }
[Input( typeof( Vector2 ) )]
[Hide]
public NodeInput GridSize { get; set; }
[Input( typeof( float ) )]
[Hide]
public NodeInput BoarderThickness { get; set; }
[InlineEditor( Label = false ), Group( "Sampler" )]
[ShowIf( nameof( ShowDefaultSamplerState ), true )]
public Sampler SamplerState { get; set; } = new Sampler();
[InputDefault( nameof( GridSize ) )]
public Vector2 DefaultGridSize { get; set; } = new Vector2( 24.0f, 24.0f );
[InputDefault( nameof( BoarderThickness ) )]
public float DefaultBoarderThickness { get; set; } = 0.420f;
[JsonIgnore, Hide, Browsable( false )]
private bool ShowDefaultSamplerState { get; set; } = false;
[Output( typeof( Vector4 ) ), Title( "Result" )]
[Hide]
public NodeResult.Func Result => ( GraphCompiler compiler ) =>
{
var coordsResult = compiler.Result( Coords );
var textureResult = compiler.Result( Texture2D );
var samplerResult = compiler.ResultSamplerOrDefault( Sampler, SamplerState );
var gridResult = compiler.ResultOrDefault( GridSize, DefaultGridSize );
var boarderThicknessResult = compiler.ResultOrDefault( BoarderThickness, DefaultBoarderThickness );
ShowDefaultSamplerState = !Sampler.IsValid;
if ( !textureResult.IsValid )
{
return NodeResult.MissingInput( "Texture2D" );
}
else if ( textureResult.ResultType is not ResultType.Texture2D )
{
return NodeResult.Error( $"Input to TexObject is not a texture object!" );
}
string func = compiler.RegisterHLSLFunction( PixelPlot, "PixelPlot" );
string funcCall = compiler.ResultHLSLFunction( func, $"{textureResult}, {samplerResult}, {(coordsResult.IsValid ? $"{coordsResult.Cast( 2 )}" : "i.vTextureCoords.xy")}, {gridResult}, {boarderThicknessResult}" );
return new NodeResult( ResultType.Vector4, funcCall );
};
}