Material: Using common functions from within custom expression nodes


for example: I have a custom function expression with for-loops and i want to call sub-functions.
This wasn’t possible because custom expression code is wrapped inside a function and hlsl doesn’t allow functions within functions.

So I searched some time and found solutions which work on former versions. (before 4.16)
Unfortunately, these tricks doesn’t work anymore.

But i found a new solution i want to share.

Goal: Write a custom voronoi function for a procedural generated texture. This function used some other custom function which has to be defined before the voronoi function.

float2 n = floor(x);
float2 f = frac(x);
// first pass: regular voronoi
float2 mg, mr;
float md = 8.0;
for (int j = -1; j <= 1; ++j)
for (int i = -1; i <= 1; ++i) {
  float2 g = float2(float(i), float(j));
  float2 o = hash2(n + g);
  float2 r = g + o - f;
  float d = dot(r, r);
  if (d < md) {
    md = d;
    mr = r;
    mg = g;
// second pass: distance to borders
md = 8.0;
for (int j = -2; j <= 2; ++j)
for (int i = -2; i <= 2; ++i) {
  float2 g = mg + float2(float(i), float(j));
  float2 o = hash2(n + g);
  float2 r = g + o - f;
  if (dot(mr - r, mr - r) > 0.00001) {
    md = min(md, dot(0.5 * (mr + r), normalize(r - mr)));
return float3(md, mr);

As you can see this function is using “hash2”, another custom function…

I create a “incCommon” Material Function:

The code which contains the custom “hash2” function is the following:

#ifndef _INC_COMMON_
#define _INC_COMMON_

  return dummy;

float foo1()
  return 123.45;

float foo2()
  return 0.0;

float3 hash2(float2 p)
  float3 p3 = frac(float3(p.xyx) * .1031);
  p3 += dot(p3, p3.yzx + 33.33);
  return frac((p3.x + p3.y) * p3.z);


  return dummy;

As you can see now, the last common function “hash2” does not write the closing bracket. Also I close the Bracket in the case, the symbol INC_COMMON isn’t defined. In the #else branch i only return the dummy float.

All i have to do now is an additional dummy parameter in my voronoi function:

Each custom material expression which is using any of my cummon functions gets this additional dummy parameter.


That’s pretty awesome if it *does *work. I always trip up when doing custom stuff like this, and forget my solutions after a bit. Thanks for sharing!