Skip to content

Create an Effect Layer

Required Elements

There are a few requirements to properly define an effect layer.

Base Class

Each effect layer needs to inherit from the base class EffectLayerBase, which implements some base functionality for your layer. However, there are some more specialized base classes available, which can further reduce the complexity of your effect layers, depending on the canvas type you are targeting.

  • EffectLayerBase: used for effect layers that target an addressable panel canvas type, or for custom handling of other canvas types.
  • StripEffectLayerBase: used for effect layers that target an addressable strip canvas type.
  • PixelEffectLayerBase: used for effect layers that target a single pixel canvas type.

Class Attribute

The class attribute EffectLayer is required to give the layer a name, category and other additional meta-information. Here is a list of properties that can be set for each render node via the attribute.

  • Name: layer name
  • Category: layer category
  • SubCategory: layer subcategory
  • Description: layer description
  • Tags: collection of layer tags
  • TargetCanvas: the target canvas type of this render node (Pixel, Strip, Panel). Default is Panel.

Constructor

Your effect layer must have a constructor with IExtensionApi, the canvas width and height as parameters. The base class requires these parameters.

Override Render Method

Override the corresponding render method of the base class and implement your render logic for the node there. See the code examples below for more information.

Optional Update Method

If your render node needs to be updated with each frame step, you can override the Update(float dt) method and implement your update logic there.

Warning

This update method is not called within the render thread. As such, you must not interact with any GPU bound render resources within this method.

Optional Initialize Method

If you need to initialize some resources for your layer, this might be the perfect place for it. It will be called from the render thread.

Optional Terminate Method

If you have initialized some resources for your layer via Initialize, you can uninitialize them here. It will be called from the render thread.

Code

EffectLayerBase

A full example of an effect layer named "Example" that fills the canvas black is displayed below.

[EffectLayer(Name = "Example")]
public class ExampleEffectLayer : EffectLayerBase
{
    public ExampleEffectLayer(IExtensionApi api, int canvasWidth, int canvasHeight)
        : base(api, canvasWidth, canvasHeight)
    {
    }

    // optional
    public override void Initialize()
    {
    }

    // optional
    public override void Terminate()
    {
    }

    // optional
    public override void Update(float dt)
    {
    }

    // required
    public override void Render(IRender render)
    {
        var canvas = render.GetCanvas();
        canvas.Clear(SKColors.Black);
    }
}

StripEffectLayerBase

The base class StripEffectLayerBase is designed to simplify creating effect layers that target a strip canvas type, where addressable pixels are aligned along the longer side of the canvas. The other canvas dimension will be duplicated from the initial strip line.

Info

Using this base class will override the TargetCanvas to Strip.

Here is an example effect layer that defines a gradient from one bindable color setting to another across the strip canvas.

[EffectLayer(Name = "Strip Gradient Fill")]
public class StripGradientColorLayer : StripEffectLayerBase
{
    [BindableLayerSetting]
    public SKColor ColorBegin { get; set; }

    [BindableLayerSetting]
    public SKColor ColorEnd { get; set; }

    public StripGradientColorLayer(IExtensionApi api, int canvasWidth, int canvasHeight)
        : base(api, canvasWidth, canvasHeight)
    {
    }

    // Notice, how this method draws a rectangle with one pixel height across the strip length.
    protected override void RenderStrip(SKCanvas canvas)
    {
        canvas.Clear();

        using var paint = new SKPaint();
        paint.Style = SKPaintStyle.Fill;
        paint.Shader = SKShader.CreateLinearGradient(new SKPoint(0, 0),
            new SKPoint(StripLength, 0),
            new[] { ColorBegin, ColorEnd },
            SKShaderTileMode.Clamp);

        canvas.DrawRect(0, 0, StripLength, 1, paint);
    }
}

PixelEffectLayerBase

The base class PixelEffectLayerBase is designed to simplify creating effect layers that target a pixel canvas type, where the color is mapped across the whole canvas.

Info

Using this base class will override the TargetCanvas to Pixel.

Here is an example of such a effect layer, which takes in a color as bindable setting, and applies it to the whole canvas.

[EffectLayer(Name = "Color Fill")]
public class FillBasicColorLayer : PixelEffectLayerBase
{
    [BindableLayerSetting]
    public SKColor Color { get; set; } = DefaultValues.PrimaryColor;

    public FillBasicColorLayer(IExtensionApi api, int canvasWidth, int canvasHeight)
        : base(api, canvasWidth, canvasHeight)
    {
    }

    // Notice, how this method only returns a single color.
    protected override SKColor RenderPixel() => Color;
}