Creating Custom Nodes for Visual Compositor
Create the node class.
The custom node class needs to inherit from the Unity.VisualCompositor.CompositorNode
base class. This class is an abstract base class, which requires a single method to be implemented:
public override void Render() { }
This method is called by the compositor when the custom node is expeced to do some work.
UI Controls
To construct controls for the UI of the custom node, use fields with a [ExposeField]
attribute.
For example:
[ExposeField] public Shader shader;
This will create a drop down field in the node for selecting a Shader object. Any serializable types can be used, and the corresponding Unity UI will be created.
Inputs
In order to get input into the custom node from the outputs of other nodes, fields with a special attribute, ([InputPort]
), are used. When the Render
method is called on the custom node, these fields will have values in them ready to be used.
For example:
[InputPort] public RenderTexture inputA;
This declares a field named inputA, which will receive a RenderTexture from some other node.
There can be as many input nodes defined with any types. The Selection Group nodes for example, output a value of type HashSet<GameObject>
.
Outputs
When the Render method is completed, it is usual to send some output values to the nodes connected to the output fields of the custom node. These are just fields with a [OutputPort]
attribute. When the method returns, all output fields are copied across to any connected nodes.
For example:
[OutputPort] public RenderTexture output;
This creates an output port which will send a RenderTexture to any connected node.
Complete Example
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.VisualCompositor;
// Any class that inherits Compositor Node will be available to use in the Compositor.
public class MyCustomNode : CompositorNode
{
// Fields that have an InputPort attribute will become input ports in the Compositor Editor.
[InputPort] public RenderTexture inputA;
// Fields that have an OutputPort attribute will become output ports in the Compositor Editor.
[OutputPort] public RenderTexture output;
// Fields that have an ExposeField attribute will have the appropriate ui controls created in
// the node editor. Any serializable field types can be used.
[ExposeField] public Shader shader;
Material mat;
// This method implements the functionality of the node. You can read from input port fields
// and write to output port fields, the Compositor takes care of moving those values around
// the graph.
public override void Render() {
if(inputA == null || shader is null) return;
if(output == null) {
output = new RenderTexture(inputA);
}
if(mat == null) {
mat = new Material(shader);
}
Graphics.Blit(inputA, output, mat);
}
}