docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Custom Function Node

    01

    Description

    The 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 to define your own input and output ports on the node itself.

    How to Use

    Use the Create Node Menu to create Custom Function nodes. By default, new Custom Function nodes don't have any input or output ports. In the Graph Inspector, open the Node Settings to access the Custom Function and Custom Port Menu menus.

    02 03

    Custom Function menu

    Menu Item Description
    Inputs A Custom Port Menu that defines the node's input ports.
    Outputs A Custom Port Menu that defines the node's output ports.
    Type A function type selector. Choose File to reference an external file or string to directly input functions to the node.
    Name Part of the name this custom function has in the final generated code. Suffixed by the function type _half or _float.
    Source An asset field to reference the external HLSL include file with the .hlsl extension. Available only in File mode.
    Body A text box where you enter HLSL code. Available only in String mode.

    Defining the Function via string

    If 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.

    04

    The example in the image above generates the following function:

    void MyFunction_float(float3 A, float B, out float3 Out)
    {
        Out  =  A + B + 1/2;
    }
    

    Defining the Function via file

    If 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.

    06

    When 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 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.

    //UNITY_SHADER_NO_UPGRADE
    #ifndef MYHLSLINCLUDE_INCLUDED
    #define MYHLSLINCLUDE_INCLUDED
    
    void MyFunction_float(float3 A, float B, out float3 Out)
    {
        Out = A + B;
    }
    #endif //MYHLSLINCLUDE_INCLUDED
    

    File mode allows for more flexibility with custom functions in a graph. You can define uniform variables outside the function scope, as shown here with a matrix.

    //UNITY_SHADER_NO_UPGRADE
    #ifndef MYHLSLINCLUDE_INCLUDED
    #define MYHLSLINCLUDE_INCLUDED
    float4x4 _MyMatrix;
    void MyFunction_float(float3 A, float B, out float3 Out)
    {
        A = mul(float4(A, 0.0), _MyMatrix).rgb;
    Out = A + B;
    }
    #endif //MYHLSLINCLUDE_INCLUDED
    

    You 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.

    //UNITY_SHADER_NO_UPGRADE
    #ifndef MYHLSLINCLUDE_INCLUDED
    #define MYHLSLINCLUDE_INCLUDED
    float3 MyOtherFunction_float(float3 In)
    {
        return In * In;
    }
    
    void MyFunction_float(float3 A, float B, out float3 Out)
    {
        A = MyOtherFunction_float(A);
        Out = A + B;
    }
    #endif //MYHLSLINCLUDE_INCLUDED
    

    You can even include other files that contain other functions.

    //UNITY_SHADER_NO_UPGRADE
    #ifndef MYHLSLINCLUDE_INCLUDED
    #define MYHLSLINCLUDE_INCLUDED
    #include "Assets/MyOtherInclude.hlsl"
    void MyFunction_float(float3 A, float B, out float3 Out)
    {
        A = MyOtherFunction_float(A);
        Out = A + B;
    }
    #endif //MYHLSLINCLUDE_INCLUDED
    

    Reusing Custom Function Nodes

    The 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 Graphs appear in the Create Node Menu, and they enable you to share or re-use your custom functions.

    11

    Create 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 and Custom Port Menu. After this, you can reuse your custom function as many times as needed, even within other Sub Graphs.

    Working with texture wires

    From 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 platforms and access data associated with textures via myInputTex.samplerstate and myInputTex.texelSize.

    Four structures are for the texture types, and one is for the sampler state:

    • UnityTexture2D
    • UnityTexture2DArray
    • UnityTexture3D
    • UnityTextureCube
    • UnitySamplerState

    CFNs 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.

    However, 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.

    How to upgrade

    1. Change all of the input and output types from Bare to non-Bare.
    • String type: Ensure that your HLSL string already uses Unity's texture access macros (such as SAMPLE_TEXTURE2D).

    • File type: Replace Bare types (such as Texture2D) with the new struct types (such as UnityTexture2D) in your function parameters.

    1. 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(...)

    From version 10.3, you can access data associated with textures via myInputTex.samplerstate and myInputTex.texelSize.


    Did you find this page useful? Please give it a rating:

    Thanks for rating this page!

    Report a problem on this page

    What kind of problem would you like to report?

    • This page needs code samples
    • Code samples do not work
    • Information is missing
    • Information is incorrect
    • Information is unclear or confusing
    • There is a spelling/grammar error on this page
    • Something else

    Thanks for letting us know! This page has been marked for review based on your feedback.

    If you have time, you can provide more information to help us fix the problem faster.

    Provide more information

    You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:

    You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:

    You've told us there is information missing from this page. Please tell us more about what's missing:

    You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:

    You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:

    You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:

    You've told us this page has a problem. Please tell us more about what's wrong:

    Thank you for helping to make the Unity documentation better!

    Your feedback has been submitted as a ticket for our documentation team to review.

    We are not able to reply to every ticket submitted.

    In This Article
    • Description
    • How to Use
      • Custom Function menu
      • Defining the Function via string
      • Defining the Function via file
      • Reusing Custom Function Nodes
      • Working with texture wires
        • How to upgrade
    Back to top
    Copyright © 2025 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)