Table of Contents

Shared code

Code that several shaders use, such as noise functions, lighting helpers or data structures, goes into shared code: a static class or a struct marked with [ShaderCode].

using Ahilevich.ShaderScript;

[ShaderCode]
public static class Waves
{
    public const float DefaultFrequency = 4;

    public static float Sine(float x, float frequency, float time)
    {
        return math.sin(x * frequency + time);
    }

    public static float Sum(float2 position, float time)
    {
        return Sine(position.x, DefaultFrequency, time) + Sine(position.y, DefaultFrequency * 1.7f, time) * 0.5f;
    }
}
// In any shader:
OUT.positionOS.y += Waves.Sum(IN.positionOS.xz, Time.y) * WaveHeight;

Create shared code with Assets > Create > Shader Script > Shared Code for a static class, or Shared Struct for a struct.

How it's used

  • Any shader, and any other [ShaderCode] type, can use shared code, as in C#.
  • Each shader includes only the shared code it actually uses, so a large library of functions doesn't make shaders bigger.
  • When shared code changes, every shader that uses it is updated.
  • The shared type must be in the same assembly as the shaders that use it: Shader Script translates source code while an assembly compiles, and can't see the source of other assemblies.

A class or struct that isn't marked with [ShaderCode] can't be used in shader code: calling it is reported as an error that suggests adding the attribute.

What shared code can contain

Shared code is either a static class, for functions and constants, or a struct, for a data type with its own methods. A [ShaderCode] class must be declared static: other classes aren't supported.

Feature Static class Struct
Static methods ✓ ✓
Instance methods — ✓
const fields ✓ ✓
Instance fields — ✓, without initial values
Other static fields, static readonly too ✗ ✗
Constructors ✗ ✗
Properties and indexers ✗ ✗
Operators and events ✗ ✗
Generic methods ✗ ✗
Nested types ✗ ✗

✓ supported, ✗ not supported, — not possible in a static class in C#.

Type and member names can't contain underscores.

What shared code can use

Shared code can use everything that doesn't belong to a particular shader: the shader types, math, ShaderApi, ShaderLib, textures passed as parameters, enums and other shared types.

What belongs to a shader isn't available in shared code: its material properties, the built-in variables such as Time, and the input and output structures such as FragmentInput. Pass the values you need as parameters:

[ShaderCode]
public static class Surface
{
    public static float3 Detail(Texture2D detailMap, float2 uv, float strength)
    {
        return detailMap.Sample(uv).rgb * strength;
    }
}

// In a shader:
float3 detail = Surface.Detail(DetailMap, uv, DetailStrength);