[Request]: Better material node for custom HLSL functions
Description
Proposal
Add a Material Editor node that calls a function from an external .hlsl file, with user-defined typed input and output pins. This is similar to Unity's Custom Function node. It would work inside Materials and Material Functions, and it would be evaluated in whichever shader stage consumes its output (including the vertex stage).
This is a smaller alternative to #3600 (full shader-based material asset). It keeps the whole material pipeline intact and only replaces the graph-node authoring for logic that is easier to write as code.
Possible Implementation
- File: Asset picker for HLSL files. The file must be under a project's
Source/Shadersfolder and is included as./<ProjectName>/<path>.hlsl, the same convention already used for Global Custom Code. - Function name: the HLSL function to call.
- Inputs: an add/remove list. Each entry has a name and a type. Each entry becomes an input pin, and the function receives the inputs as arguments in list order.
- Outputs: an add/remove list with the same structure. Each entry becomes an output pin and maps to an
outparameter, after the inputs, in list order. - Supported pin types (initial): Bool, Int, Float, Float2, Float3, Float4, Texture (2D). These are the types the shader generator's
writeLocalandValue::Castalready handle. - Pin names come from the list entries, so connecting the node stays as easy as with any other node.
- Limits: up to 16 inputs and 16 outputs, like
Function.FunctionNode.
Additional Request (Optional)
Expose an inverse view-projection matrix in the per-view material constants (ViewData). This makes screen-space effects possible in a function without workarounds. Consider making material constants easily accessible.
Benefits
Complex logic is cumbersome to build from graph nodes, and hard to maintain, diff and reuse.
The existing options fall short:
- Custom Code node has 8 fixed
float4inputs and 4 fixedfloat4outputs. Every input is cast tofloat4, texture inputs are not supported, and the code is stored inline in the graph (no IDE workflow, no reuse across materials). - Custom Global Code node +
#includeallows including files fromSource/Shaders, but you still need a Custom Code node to call the function. That node has the limits above, and there are no typed or named pins.
Source: FlaxEngine/FlaxEngine