原文:Custom Nodes with CodeFunctionNode@Unity Docs
随着Unity发布了ShaderGraph,创建一个Shader比以往都要更加容易。然而无论提供多少个默认节点,都不能满足用户的自定义需求。因此,我们开发了一个自定义节点的API,可以在C#中创建新节点。或许能满足用户们刁钻的需求。
本文将介绍一种最简单的实现方法,称之为Code Function Node,接下来将展示详细细节。
让我们先创建一个C#脚本,在这个例子中,我们将脚本命名为MyCustomNode
。为了使用Code Function Node API,需要引入UnityEditor.ShaderGraph
并继承父类CodeFunctionNode
。
1 | using UnityEngine; |
由于CodeFunctionNode
仍是虚类,故接下来我们将实现其中要求我们实现的函数。
方法GetFunctionToConvert
使用反射将一段方法转化为ShaderGraph可用的方法信息(MethodInfo)。
如下添加引用System.Reflection
并重写GetFunctionToConvert
方法,注意”MyCustomFunction”这段字符串正对应着我们要实现的Shader函数名,我们将在稍后实现。至此一个节点便完成了,同时在构造函数中设置name
成员可以指定该Node在ShderGraph中显示的标题。
1 | using UnityEngine; |
接下来我们实现MyCustomFunction
函数。
首先创建一个返回字符串的静态方法,在参数中我们可以定义当前Node的端口(Port)。这些端口名将直接映射到最终实现Shader中的参数名。这个例子中我们将设置两个输入的端口A
和B
,数据格式都是动态维度向量(Dynamic Dimension Vector),同时输出一个动态维度向量Out
。这一组端口便构成了一个Node的所有节点。同时我们需要添加Slot
属性以区分不同的id。
1 | static string MyCustomFunction( |
更详细的数据格式列表请查阅API文档或文末附录。
这个函数需要返回一个包含着色器程序的字符串,如HLSL语句。本例中我们将定义一个Out=A+B
的简单函数,这个函数大致如下:
1 | static string MyCustomFunction( |
最后我们需要将这个节点显示再节点列表中,以供选择。这要求我们为类添加一个属性。如下添加,最后一个字符串将作为节点在节点列表中的显示名字(区别于显示在节点上方的节点标题)其余为分类文件夹。
1 | [ ] |
这样一来我们就创建好了一个自定义节点,可以在ShaderGraph中尽情使用了!
其他例子
除了Out = A + B
,我们还可以定义很多东西。下面这个例子展示了如何在三个多维向量中选取最小值。
1 | static string Min3( |
下面这个例子是通过一个布尔值决定是否反转法向量。其中Normal
端口被绑定为世界坐标法线(World Space Normal),即没有线段连入这个端口是,默认使用世界坐标法线。
1 | static string Min3( |
附录
Port Types
Argument Type | Data Type |
---|---|
Boolean | Boolean |
Vector1 | Vector1 |
Vector2 | Vector2 |
Vector3 | Vector3 |
Vector4 | Vector4 |
Color | Vector4 (with a ColorRGBA Port Binding) |
ColorRGBA | Vector4 (with a ColorRGBA Port Binding) |
ColorRGB | Vector3 (with a ColorRGB Port Binding) |
Texture2D | Texture2D |
Texture2DArray | Texture2DArray |
Texture3D | Texture3D |
Cubemap | Cubemap |
SamplerState | SamplerState |
DynamicDimensionVector | DynamicVector |
Matrix4x4 | Matrix4 |
Matrix3x3 | Matrix3 |
Matrix2x2 | Matrix2 |
DynamicDimensionMatrix | DynamicMatrix |