Editor/ShaderGraphPlus/Nodes/SceneColor.cs
using Sandbox.Rendering;
namespace ShaderGraphPlus.Nodes;
/// <summary>
/// Color of the scene.
/// </summary>
[Title( "Scene Color" ), Category( "Variables" ), Icon( "palette" )]
public sealed class SceneColorNode : ShaderNodePlus
{
[JsonIgnore, Hide, Browsable( false )]
public override Color NodeTitleColor => ShaderGraphPlusTheme.NodeHeaderColors.FunctionNode;
[Hide]
public string MapSceneColorCoords => @"
float2 MapSceneColorCoords( float2 vInput, float2 vModes )
{
float2 result;
// X
if ( vModes.x == 1 ) // Mirror
{
float xx = abs( vInput.x );
result.x = ( fmod( floor( xx ), 2.0f ) == 0.0f ) ? frac( xx ) : 1.0f - frac( xx );
}
else if ( vModes.x == 2 ) // Clamp
{
result.x = clamp( vInput.x, 0.0f, 1.0f );
}
else if ( vModes.x == 3 ) // Border
{
result.x = ( vInput.x < 0.0f || vInput.x > 1.0f ) ? 0.5f : vInput.x;
}
else if ( vModes.x == 4 ) // MirrorOnce
{
float xx = abs( vInput.x );
float floorX = floor( xx );
if ( floorX < 1.0f )
{
result.x = frac( xx );
}
else if ( floorX < 2.0f )
{
result.x = 1.0f - frac( xx );
}
else
{
result.x = vInput.x;
}
}
else // Wrap by default
{
result.x = vInput.x;
}
// Y
if ( vModes.y == 1 ) // Mirror
{
float yy = abs( vInput.y );
result.y = ( fmod( floor( yy ), 2.0f ) == 0.0f ) ? frac( yy ) : 1.0f - frac( yy );
}
else if ( vModes.y == 2 ) // Clamp
{
result.y = clamp( vInput.y, 0.0f, 1.0f );
}
else if ( vModes.y == 3 ) // Border
{
result.y = ( vInput.y < 0.0f || vInput.y > 1.0f ) ? 0.5f : vInput.y;
}
else if ( vModes.y == 4 ) // MirrorOnce
{
float yy = abs( vInput.y );
float floorY = floor( yy );
if ( floorY < 1.0f )
{
result.y = frac( yy );
}
else if ( floorY < 2.0f )
{
result.y = 1.0f - frac( yy );
}
else
{
result.y = vInput.y;
}
}
else // Wrap by default
{
result.y = vInput.y;
}
return result;
}
";
[Input( typeof( Vector2 ) )]
[Hide]
public NodeInput Coords { get; set; }
public TextureAddressMode AddressU { get; set; } = TextureAddressMode.Wrap;
public TextureAddressMode AddressV { get; set; } = TextureAddressMode.Wrap;
[Output( typeof( Vector3 ) )]
[Hide]
public NodeResult.Func SceneColor => ( GraphCompiler compiler ) =>
{
var inputCoords = compiler.Result( Coords );
var graph = compiler.Graph;
if ( graph.Domain != ShaderDomain.PostProcess && graph.BlendMode != BlendMode.Translucent )
{
return NodeResult.Error( $"Graph \"{nameof( BlendMode )}\" must be set to \"{nameof( BlendMode.Translucent )}\" in order to use \"{DisplayInfo.Name}\"" );
}
var uvModes = $"float2( {(int)AddressU}, {(int)AddressV} )";
var func = compiler.RegisterHLSLFunction( MapSceneColorCoords, "MapSceneColorCoords" );
var coords = inputCoords.IsValid ? compiler.ResultHLSLFunction( func, inputCoords.Cast( 2 ), uvModes ) : $"CalculateViewportUv( {compiler.ResultHLSLFunction( func, "i.vPositionSs.xy", uvModes )} )";
if ( graph.Domain is ShaderDomain.PostProcess )
{
return new NodeResult( ResultType.Vector3, $"g_tColorBuffer.Sample( g_sAniso, {coords} ).rgb" );
}
compiler.RegisterGlobal( "bWantsFBCopyTexture", "BoolAttribute( bWantsFBCopyTexture, true );" );
compiler.RegisterGlobal( "g_tFrameBufferCopyTexture", "Texture2D g_tFrameBufferCopyTexture < Attribute( \"FrameBufferCopyTexture\"); SrgbRead( false ); >;" );
return new NodeResult( ResultType.Vector3, $"g_tFrameBufferCopyTexture.Sample( g_sAniso, {coords}{(compiler.IsPreview ? " * g_vFrameBufferCopyInvSizeAndUvScale.zw" : "")} ).rgb" );
};
}
[Title( "Frame Buffer Copy Inv Size And Uv Scale" ), Category( "Variables" )]
public sealed class FrameBufferCopyInvSizeAndUvScaleNode : ShaderNodePlus
{
[JsonIgnore, Hide, Browsable( false )]
public override Color NodeTitleColor => Color.Parse( "#803334" )!.Value;
[Output( typeof( Vector2 ) )]
[Hide]
public NodeResult.Func Result => ( GraphCompiler compiler ) =>
{
return new NodeResult( ResultType.Vector2, $"g_vFrameBufferCopyInvSizeAndUvScale.zw", true );
};
}