A game about forced loneliness, made by TACStudios
1# Custom Function Node
2
3
4
5## Description
6
7The Custom Function Node enables you to inject your own custom HLSL code in Shader Graphs. This provides you with an extra level of control when you need it (for example, to do some fine-grained optimization). You can either write small functions directly into graphs by using the string mode, or reference external HLSL include files. Use the [Custom Port Menu](Custom-Port-Menu.md) to define your own input and output ports on the node itself.
8
9## How to Use
10
11Use the [Create Node Menu](Create-Node-Menu.md) to create Custom Function nodes. By default, new Custom Function nodes don't have any input or output ports.
12In the [Graph Inspector](Internal-Inspector.md), open the **Node Settings** to access the Custom Function and [Custom Port Menu](Custom-Port-Menu.md) menus.
13
14 
15
16### Custom Function menu
17
18| Menu Item | Description |
19|:----------|:------------|
20| Inputs | A [Custom Port Menu](Custom-Port-Menu.md) that defines the node's input ports. |
21| Outputs | A [Custom Port Menu](Custom-Port-Menu.md) that defines the node's input ports. |
22| Type | A function type selector. Choose File to reference an external file or string to directly input functions to the node. |
23| Name | Part of the name this custom function has in the final generated code. Suffixed by the function type ` _half ` or ` _float `. |
24| Source | An asset field to reference the external HLSL include file. **Only available in `File` mode**. |
25| Body | A text box where you enter HLSL code. **Only available in `String` mode**. |
26
27### Defining the Function via string
28If you select `String` mode, the graph generates the shader function. The `Name` field defines the name of the generated function, and the `Body` field defines the contents of the generated function. Unity handles the arguments, braces, and indent scope automatically. In `String` mode you may use the token `$precision` instead of `half` or `float` in the `Body` field. Unity replaces this with the correct type, based on that node's precision, when the node is processed.
29
30
31
32The example in the image above generates the following function:
33
34```
35void MyFunction_float(float3 A, float B, out float3 Out)
36{
37 Out = A + B + 1/2;
38}
39```
40
41### Defining the Function via file
42
43If you select `File` mode, the graph does not automatically generate the shader function. This mode injects an include reference in the final generated shader, and uses a function from within the referenced file. The `Name` field must match the name of the function you wish to call. The `Source` field contains a reference to the HLSL file that includes the function.
44
45
46
47When you use `File` mode for the Custom Function node, you must manually format the functions properly. One thing to note when creating custom functions for [Shader Graph](index.md) is the precision suffixes. The generated code appends a precision suffix to function names. Your include file function must also append your desired precision suffix (shown below with `_float`), or contain multiple functions with both `_float` and `_half` suffixes, but your `Name` field **must not include the precision suffix**.
48
49```
50//UNITY_SHADER_NO_UPGRADE
51#ifndef MYHLSLINCLUDE_INCLUDED
52#define MYHLSLINCLUDE_INCLUDED
53
54void MyFunction_float(float3 A, float B, out float3 Out)
55{
56 Out = A + B;
57}
58#endif //MYHLSLINCLUDE_INCLUDED
59```
60
61`File` mode allows for more flexbility with custom functions in a graph. You can define uniform variables outside of the function scope, as shown here with a matrix.
62
63```
64//UNITY_SHADER_NO_UPGRADE
65#ifndef MYHLSLINCLUDE_INCLUDED
66#define MYHLSLINCLUDE_INCLUDED
67float4x4 _MyMatrix;
68void MyFunction_float(float3 A, float B, out float3 Out)
69{
70 A = mul(float4(A, 0.0), _MyMatrix).rgb;
71Out = A + B;
72}
73#endif //MYHLSLINCLUDE_INCLUDED
74```
75
76You can define multiple functions in the same file, and call them from your referenced function. Alternatively, you can reference the same file, but use different functions from different Custom Function nodes.
77
78```
79//UNITY_SHADER_NO_UPGRADE
80#ifndef MYHLSLINCLUDE_INCLUDED
81#define MYHLSLINCLUDE_INCLUDED
82float3 MyOtherFunction_float(float3 In)
83{
84 return In * In;
85}
86
87void MyFunction_float(float3 A, float B, out float3 Out)
88{
89 A = MyOtherFunction_float(A);
90 Out = A + B;
91}
92#endif //MYHLSLINCLUDE_INCLUDED
93```
94
95You can even include other files that contain other functions.
96
97```
98//UNITY_SHADER_NO_UPGRADE
99#ifndef MYHLSLINCLUDE_INCLUDED
100#define MYHLSLINCLUDE_INCLUDED
101#include "Assets/MyOtherInclude.hlsl"
102void MyFunction_float(float3 A, float B, out float3 Out)
103{
104 A = MyOtherFunction_float(A);
105 Out = A + B;
106}
107#endif //MYHLSLINCLUDE_INCLUDED
108```
109
110### Reusing Custom Function Nodes
111
112The Custom Function node, on its own, is a single node instance. If you wish to re-use the same custom functions without re-creating the inputs, outputs, and function referencing, use [Sub Graphs](Sub-graph.md). Sub Graphs appear in the [Create Node Menu](Create-Node-Menu.md), and they enable you to share or re-use your custom functions.
113
114
115
116Create your custom function either directly in a Sub Graph, or right-click the existing Custom Function node and select `Convert to Sub Graph`. To add the appropriate input and output ports, use the [Graph Inspector](Internal-Inspector.md) and [Custom Port Menu](Custom-Port-Menu.md). After this, you can reuse your custom function as many times as needed, even within other Sub Graphs.
117
118### Working with texture wires
119
120From version 10.3, Shader Graph has five new data structures to ensure that Custom Function Nodes (CFNs) and SubGraphs input and output data from texture wires in a consistent way. The new structures also make it possible for SamplerState to compile on [GLES2](https://en.wikipedia.org/wiki/OpenGL_ES#OpenGL_ES_2.0) platforms and access data associated with textures via `myInputTex.samplerstate` and `myInputTex.texelSize`.
121
122Four structures are for the texture types, and one is for the sampler state:
123
124* UnityTexture2D
125* UnityTexture2DArray
126* UnityTexture3D
127* UnityTextureCube
128* UnitySamplerState
129
130CFNs you create with earlier versions of Shader Graph continue to work after this change. As part of the automatic update, Unity transitions them to the new **Bare** node type. This type replicates the old input and output behavior. All other types pass the new structs.
131
132However, you should manually upgrade CFNs that produce texture or samplerstate types as output to ensure that they behave consistently—and to gain the benefits of the new design. Unity flags this type of outdated Custom Function Nodes with a warning when you open your Shader Graph in 10.3 or later.
133
134#### How to upgrade
135
1361. Change all of the input and output types from **Bare** to **non-Bare**.<br/>
137
138* **String** type: Ensure that your HLSL string already uses Unity's texture access macros (such as `SAMPLE_TEXTURE2D`).
139
140* **File** type: Replace Bare types (such as Texture2D) with the new struct types (such as UnityTexture2D) in your function parameters.
141
1422. If your HLSL code is using platform-specific or non-standard texture operations, you'll need to convert the way you access textures to take that structure into account. For example, `myInputTex.GetDimensions(...)` would become `myInputTex.tex.GetDimensions(...)`
143
144
145From version 10.3, you can access data associated with textures via `myInputTex.samplerstate` and `myInputTex.texelSize`.