Unity PolySpatial Custom Function Node Support
PolySpatial's shader graph conversion provides partial support for the Custom Function Node by parsing a limited subset of HLSL and converting it into MaterialX nodes. Note that this does not allow for any functionality beyond that which is possible by combining built-in shader graph nodes; it simply provides an alternate means of specification that may be more compact or convenient for some purposes.
The parser used for custom function nodes is primitive compared to a full HLSL implementation, and is under active development.
Source Types
Both the File
and String
values for the Type
property are supported. String
sources consist of a single function body, as described below. File
sources consist of one or more function definitions, with the Name
property determining which function will serve as the "main" function for the node. File sources have the following limitations:
- Preprocessor definitions (such as
#include
) are ignored. - The file cannot contain any declarations other than functions (such as uniform variables).
- All function calls are expanded inline. Recursion is not supported.
- Only
float
precision is supported (the "main" function name must always end with_float
).
Function Body Format
Custom function bodies should consist of a series of assignment statements for either temporary variables or outputs. Variables may be reassigned using the =
or compound assignment operators.
Example
The following shows an example of a supported function body. Note that the body consists only of assignment statements, assigning one temporary variable and using it to set the value of an output.
float2 xy = float2(In.r * In.a, In.g) * 2.0 - 1.0;
Out = float3(xy, max(1.0e-16, sqrt(1.0 - saturate(dot(xy, xy)))));
Supported Types
The parser recognizes scalar, vector, and matrix floating point types: float
, float2
, float3
, float4
, float2x2
, float3x3
, float4x4
. The UnityTexture2D
, UnityTexture3D
, UnityTextureCube
, and UnitySamplerState
types can be used as function parameters in order to pass them to macros (such as SAMPLE_TEXTURE2D
), but no other operations are supported for them.
Supported Operators
The parser supports basic arithmetic operators (+
, -
, *
, /
, %
) for float
, vector, and matrix values and logic/comparison operators (!
, &&
, ||
, ==
, !=
, >
, <
, >=
, <=
) for float
values. The conditional operator (?:
) is supported for float
conditions and float
or vector values. The =
operator is supported for assignment/reassignment, and the arithmetic compound assignment operators (+=
, -=
, *=
, /=
, %=
, ++
, --
) are supported for reassignment.
Swizzling
Swizzling vector values is supported. For example, float3(1, 2, 3).xz
is equivalent to float2(1, 3)
. Swizzling is also supported for reassignment. For example, if foo
is a float3
, then foo.xy = float2(1, 3)
is equivalent to foo = float3(1, 3, foo.z)
.
Supported Functions
HLSL Intrinsic Functions
The parser supports a subset of HLSL's intrinsic functions: abs
, acos
, all
, any
, asin
, atan
, atan2
, ceil
, clamp
, cos
, cosh
, cross
, degrees
, distance
, dot
, exp
, exp2
, floor
, fmod
, frac
, isinf
, isnan
, length
, lerp
, log
, max
, min
, mul
, normalize
, pow
, radians
, rcp
, reflect
, refract
, round
, rsqrt
, saturate
, sign
, sin
, sinh
, smoothstep
, sqrt
, step
, tan
, tanh
, transpose
, trunc
PolySpatial-Specific Functions
Additionally, the parser supports the custom splitlr
function, which implements the splitlr function described in the MaterialX Spec:
genType splitlr(genType valuel, genType valuer, float center, float2 texcoord);
(where genType
is one of float
, float2
, float3
, or float4
)
Unity Macros
For sampling textures, the parser supports Unity macros: SAMPLE_TEXTURE2D
, SAMPLE_TEXTURE2D_LOD
, SAMPLE_TEXTURE3D
, SAMPLE_TEXTURE3D_LOD
, SAMPLE_TEXTURECUBE_LOD
Supported Globals
The parser supports several of Unity's built-in global variables: _Time
, _SinTime
, _CosTime
, unity_DeltaTime
, unity_ObjectToWorld
, unity_WorldToObject
, UNITY_MATRIX_V
, UNITY_MATRIX_I_V
, UNITY_MATRIX_P
, UNITY_MATRIX_I_P
, UNITY_MATRIX_VP
, UNITY_MATRIX_I_VP
Note: Currently, the object-to-world matrix supplied by visionOS (and thus unity_ObjectToWorld
and unity_WorldToObject
) includes the transform of the rendered volume: that is, moving the (bounded) application around in space affects its world transform, unlike the world position output from the Position Node, which is relative to the transform of the rendered volume and thus does not change when the application is repositioned.