Attributes and Variables
Attributes are the bridge to pass information around the CPU to the GPU, like Variables, Textures or entire Buffers.
What's an attribute
Attributes are the bridge to pass information around the CPU to the GPU, like Variables, Textures or entire Buffers.
To declare a constant to be exposed to C# you simply append < Attribute("Foo"); >; to that variable, like for example:
bool NoiseEnabled < Attribute("NoiseEnabled"); >;float4 NoiseScale < Attribute("NoiseScale"); >;float4x4 BoxTransform < Attribute("BoxTransform"); >;Texture2D NoiseTexture < Attribute("NoiseTexture"); >;
This can then be set from C# side with Attributes.Set( "Name", variable );
Material Editor Integration
The Material Editor provides a graphical interface to adjust and control attributes defined in your shaders, By setting a Default[1..4]() value it will make it show up on the editor.
Certain attributes can have custom UI behaviors. For instance, UiType(Color) turns a float3 into a color picker. Other UI hints can be used to provide default values and ranges.
float3 TintColor < UiType(Color); Default3(1.0, 1.0, 1.0) >;
Reference
The following attributes are supported for constants:
Default(arg1) or Default1(arg1) Defines a variable default1 with the value { arg1 }.
Default2(arg1, arg2) Defines a float2/int2 with values { arg1, arg2 }.
Default3(arg1, arg2, arg3) Defines a float3/int3 with default values { arg1, arg2, arg3 }.
Default4(arg1, arg2, arg3, arg4) Defines a float4 with values { arg1, arg2, arg3, arg4 }.
Range( arg ) - Limit the UI to this range
Range2( arg, arg2 ) - Limits the UI of a float2/int2 to this range
Range3( arg, arg2, arg3 ) - Limits the UI of a float2/int2 to this range
Range4( arg, arg2, arg3, arg4 ) - Limits the UI of a float2/int2 to this range
UIType( type ) - Explicitly set which UI type to use for this variable
DefaultFile( arg ) - Defaults to this file if none is specified, for Textures
Textures
You can define an image to use on the material editor UI as follows:
CreateInputTexture2D(
Name,
ColorSpace, // Color space: Linear or SRGB
Precision, // Precision per channel (e.g. 8 for 8-bit)
Format, // Format (e.g., DXT5, BC7)
"Suffix", // File suffix to filter in the UI
"Group,1/10", // UI group and ordering
Default(0.5) // Default value if none is provided
);
For example, this will create an "AlbedoImage" that can be exposed to the texture for compiling, the UI will filter for images that end with _albedo suffix:
CreateInputTexture2D( AlbedoImage, Linear, 8, "", "_albedo", "Material,10/30", Default( 0.5 ) );
To expose the compiled texture from UI into a Texture2D you can use the following:
Texture2D Albedo < Channel( RGBA, Box( AlbedoImage ) ); >;
This compiles an image into a texture using box filtering for mipmaps.
Advanced Usage
You can pack channels of multiple images into a single texture specifying which channel the image will be sampled from
Texture2D RMA < Channel( R, Box( Roughness ), Linear );
Channel( G, Box( Metalness ), Linear );
Channel( B, Box( Occlusion ), Linear );
Channel( A, Box( BlendMask ), Linear ); >;
GPU Buffers
If you want to send a lot of information at once you can use Constant Buffers or Structured Buffers:
private struct Constants
{
public Vector4 Foo;
public Vector4 Bar;
}
private Rendering.CommandList ConstantsCommandList()
{
Rendering.CommandList commands = new("Example Commmand List");
var constants = new Constants();
constants.Foo = new Vector4( 0.0f, 1.0f, 2.0f, 3.0f );
constants.Bar = new Vector4( 4.0f, 5.0f, 6.0f, 7.0f );
commands.SetConstantBuffer( "Constants", constants );
return commands;
}
And in the shader it can just be defined as mirrored on C#, for Constant Buffers the attribute binding for it's name is already implicitly set.
cbuffer Constants
{
float4 Foo;
float4 Bar;
}
Attributes on SceneObjects
You can set attributes of a specific SceneObject, this will affect the materials that are being used on that object when rendering, it does not need to be in a render block.
void UpdateObject()
{
if ( !_sceneObject.IsValid() )
return;
_sceneObject.Attributes.SetCombo( "D_COMBO", 1 );
_sceneObject.Attributes.Set( "Foo", 1.0f );
_sceneObject.Attributes.Set( "Bar", new Vector4( 1.0f, 2.0f, 3.0f, 4.0f ) );
_sceneObject.Attributes.Set( "NoiseTexture", NoiseTexture );
}
Attributes on Command Lists
You can use attributes on the entire render context or the rest of the pipeline when you set them on a Command List.
protected override void OnEnabled()
{
Camera.AddCommandList( ExampleCommandList(), Rendering.Stage.AfterDepthPrepass );
}
private Rendering.CommandList ExampleCommandList()
{
Rendering.CommandList commands = new("Example Commmand List");
var compute = new ComputeShader( "example_cs" );
commands.Set( "NoiseScale", NoiseScale );
commands.Set( "NoiseTexture", NoiseTexture );
commands.DispatchCompute( compute, ExampleRenderTarget.Size );
// Sets attribute for anything after Rendering.Stage.AfterDepthPrepass
// until end of frame for this view from the result of the compute operation
commands.SetGlobal( "Result", ExampleRenderTarget );
return commands;
}
Referenced API
Canonical API pages mentioned in this guide.
Represents a color using 4 floats (rgba), with 0-1 range.
A 4-dimensional vector/point.
A generic checkbox widget.
No summary available.
Like a widget - but is drawn
Variables have a name and type, and are local to each invocation of an `Facepunch.ActionGraphs.Variable.ActionGraph`. They are assigned with a `!:NodeLibrary.SetVar` node, and read with `!:NodeLibrary.GetVar`.
No summary available.
A compute shader is a program that runs on the GPU, often with data provided to/from the CPU by means of a `Sandbox.GpuBuffer` or a `Sandbox.Texture`.