material

MF_PerlinNoise_3D

  • Exposure: public
  • UE Version: 5.7

avatar author

XavierPan

December 14, 2025, 2:01 pm

define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))

define final(a, b, c) \

{ \ c ^= b; \ c -= rot(b, 14); \ a ^= c; \ a -= rot(c, 11); \ b ^= a; \ b -= rot(a, 25); \ c ^= b; \ c -= rot(b, 16); \ a ^= c; \ a -= rot(c, 4); \ b ^= a; \ b -= rot(a, 14); \ c ^= b; \ c -= rot(b, 24); \ }

define FLOORFRAC(x, x_int, x_fract) { float x_floor = floor(x); x_int = int(x_floor); x_fract = x - x_floor; }

struct MathBaseLib { float3 compatibleMod(float3 a, float b) { float3 result; result.x = compatibleMod(a.x, b); result.y = compatibleMod(a.y, b); result.z = compatibleMod(a.z, b); return result; } float compatibleMod(float a, float b) { if (b != 0.0f) { int N = (int)(a / b); return a - N * b; } else return 0.0f; } };

struct NoiseFunction { MathBaseLib mbl; float triMix(float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float x, float y, float z) { float x1 = 1.0 - x; float y1 = 1.0 - y; float z1 = 1.0 - z; return z1 (y1 (v0 x1 + v1 x) + y (v2 x1 + v3 x)) + z (y1 (v4 x1 + v5 x) + y (v6 x1 + v7 x)); } float fade(float t) { return t t t (t (t * 6.0 - 15.0) + 10.0); } float negateIf(float value, uint condition) { return (condition != 0u) ? -value : value; } float noiseGrad(uint hash, float x, float y, float z) { uint h = hash & 15u; float u = h < 8u ? x : y; float vt = ((h ==12u) || (h == 14u)) ? x : z; float v = h < 4u ? y : vt; return negateIf(u, h & 1u) + negateIf(v, h & 2u); } float noisePerlin(float3 vec) { int X, Y, Z; float fx, fy, fz;

FLOORFRAC(vec.x, X, fx);
FLOORFRAC(vec.y, Y, fy);
FLOORFRAC(vec.z, Z, fz);

float u = fade(fx);
float v = fade(fy);
float w = fade(fz);
float r = triMix(noiseGrad(hashInt3(X, Y, Z), fx, fy, fz), noiseGrad(hashInt3(X + 1, Y, Z), fx - 1, fy, fz),
                  noiseGrad(hashInt3(X, Y + 1, Z), fx, fy - 1, fz), noiseGrad(hashInt3(X + 1, Y + 1, Z), fx - 1, fy - 1, fz),
                  noiseGrad(hashInt3(X, Y , Z + 1), fx, fy, fz - 1), noiseGrad(hashInt3(X + 1, Y, Z + 1), fx - 1, fy, fz - 1),
                  noiseGrad(hashInt3(X, Y + 1, Z +1), fx, fy - 1, fz - 1), noiseGrad(hashInt3(X + 1, Y + 1, Z +1), fx - 1, fy - 1, fz - 1),
                  u, v, w);
return r;

} float noiseScale3(float result) { return 0.9820f result; } float snoise(float3 p) { float3 precisionCorrection = 0.5 float3((float)(abs(p.x) >= 1000000.0), (float)(abs(p.y) >= 1000000.0), (float)(abs(p.z) >= 1000000.0));

p = mbl.compatibleMod(p, 100000.0) + precisionCorrection;
return noiseScale3(noisePerlin(p));

} float safeSnoise(float3 co) { float3 precisionCorrection = 0.5 * float3((float)(abs(co.x) >= 1000000.0), (float)(abs(co.y) >= 1000000.0), (float)(abs(co.z) >= 1000000.0)); float3 p = fmod(co, 100000.0) + precisionCorrection; return snoise(p); } uint hashUint2(uint kx, uint ky) { uint a,b,c; a = b = c = 0xdeadbeff + (4 << 2) + 13;

a += ky;
b += kx;
final(a, b, c);

return c;

} uint hashUint3(uint kx, uint ky, uint kz) { uint a, b, c; a = b = c = 0xdeadbeefu + (3u << 2u) + 13u;

c += kz; b += ky; a += kx; final(a, b, c);

return c; } uint hashInt3(int kx, int ky, int kz) { return hashUint3((uint)kx, (uint)ky, (uint)kz); } float hashUint2ToFloat(uint kx, uint ky) { return float(hashUint2(kx, ky) / float(0xFFFFFFFFu)); } float hashVec2ToFloat(float2 k) { return hashUint2ToFloat(asuint(k.x), asuint(k.y)); } float3 randomVector3Offset(float seed) { return float3(100 + hashVec2ToFloat(float2(seed, 0)) 100, 100 + hashVec2ToFloat(float2(seed, 1)) 100,100 + hashVec2ToFloat(float2(seed, 2)) * 100); } float noiseFbm(float3 co, float detail, float roughness, float lacunarity, int useNormalize) { float3 p = co; float fscale = 1.0; float amp = 1.0; float maxamp = 0.0; float sum = 0.0;

for (int i = 0; i <= (int)detail; i++)
{
  float t = safeSnoise(fscale * p);
  sum += t * amp;
  maxamp += amp;
  amp *= roughness;
  fscale *= lacunarity;
}
float rmd = frac(detail);
if (rmd != 0)
{
  float t = safeSnoise(fscale * p);
  float sum2 = sum + t * amp;
  return (useNormalize == 1) ? lerp(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : lerp(sum, sum2, rmd);
}
else
  return (useNormalize == 1) ? (0.5 * sum / maxamp + 0.5) : sum;

} };

//main NoiseFunction nf; float3 color = 0; color.r = nf.noiseFbm(coord, detail, roughness, lacunarity, normalize); color.g = nf.noiseFbm(coord + nf.randomVector3Offset(3.0), detail, roughness, lacunarity, normalize); color.b = nf.noiseFbm(coord + nf.randomVector3Offset(4.0), detail, roughness, lacunarity, normalize); Color = color; return color.r;

Click the button above, it will automatically copy blueprint in your clipboard. Then in Unreal Engine blueprint editor, paste it with ctrl + v

1 comment

  • avatar author

    XavierPan

    December 14, 2025, 2:02 pm

    define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))

    define final(a, b, c) \

    { \ c ^= b; \ c -= rot(b, 14); \ a ^= c; \ a -= rot(c, 11); \ b ^= a; \ b -= rot(a, 25); \ c ^= b; \ c -= rot(b, 16); \ a ^= c; \ a -= rot(c, 4); \ b ^= a; \ b -= rot(a, 14); \ c ^= b; \ c -= rot(b, 24); \ }

    define FLOORFRAC(x, x_int, x_fract) { float x_floor = floor(x); x_int = int(x_floor); x_fract = x - x_floor; }

    struct MathBaseLib { float3 compatibleMod(float3 a, float b) { float3 result; result.x = compatibleMod(a.x, b); result.y = compatibleMod(a.y, b); result.z = compatibleMod(a.z, b); return result; } float compatibleMod(float a, float b) { if (b != 0.0f) { int N = (int)(a / b); return a - N * b; } else return 0.0f; } };

    struct NoiseFunction { MathBaseLib mbl; float triMix(float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float x, float y, float z) { float x1 = 1.0 - x; float y1 = 1.0 - y; float z1 = 1.0 - z; return z1 (y1 (v0 x1 + v1 x) + y (v2 x1 + v3 x)) + z (y1 (v4 x1 + v5 x) + y (v6 x1 + v7 x)); } float fade(float t) { return t t t (t (t * 6.0 - 15.0) + 10.0); } float negateIf(float value, uint condition) { return (condition != 0u) ? -value : value; } float noiseGrad(uint hash, float x, float y, float z) { uint h = hash & 15u; float u = h < 8u ? x : y; float vt = ((h ==12u) || (h == 14u)) ? x : z; float v = h < 4u ? y : vt; return negateIf(u, h & 1u) + negateIf(v, h & 2u); } float noisePerlin(float3 vec) { int X, Y, Z; float fx, fy, fz;

    FLOORFRAC(vec.x, X, fx);
    FLOORFRAC(vec.y, Y, fy);
    FLOORFRAC(vec.z, Z, fz);
    
    float u = fade(fx);
    float v = fade(fy);
    float w = fade(fz);
    float r = triMix(noiseGrad(hashInt3(X, Y, Z), fx, fy, fz), noiseGrad(hashInt3(X + 1, Y, Z), fx - 1, fy, fz),
                      noiseGrad(hashInt3(X, Y + 1, Z), fx, fy - 1, fz), noiseGrad(hashInt3(X + 1, Y + 1, Z), fx - 1, fy - 1, fz),
                      noiseGrad(hashInt3(X, Y , Z + 1), fx, fy, fz - 1), noiseGrad(hashInt3(X + 1, Y, Z + 1), fx - 1, fy, fz - 1),
                      noiseGrad(hashInt3(X, Y + 1, Z +1), fx, fy - 1, fz - 1), noiseGrad(hashInt3(X + 1, Y + 1, Z +1), fx - 1, fy - 1, fz - 1),
                      u, v, w);
    return r;

    } float noiseScale3(float result) { return 0.9820f result; } float snoise(float3 p) { float3 precisionCorrection = 0.5 float3((float)(abs(p.x) >= 1000000.0), (float)(abs(p.y) >= 1000000.0), (float)(abs(p.z) >= 1000000.0));

    p = mbl.compatibleMod(p, 100000.0) + precisionCorrection;
    return noiseScale3(noisePerlin(p));

    } float safeSnoise(float3 co) { float3 precisionCorrection = 0.5 * float3((float)(abs(co.x) >= 1000000.0), (float)(abs(co.y) >= 1000000.0), (float)(abs(co.z) >= 1000000.0)); float3 p = fmod(co, 100000.0) + precisionCorrection; return snoise(p); } uint hashUint2(uint kx, uint ky) { uint a,b,c; a = b = c = 0xdeadbeff + (4 << 2) + 13;

    a += ky;
    b += kx;
    final(a, b, c);
    
    return c;

    } uint hashUint3(uint kx, uint ky, uint kz) { uint a, b, c; a = b = c = 0xdeadbeefu + (3u << 2u) + 13u;

    c += kz; b += ky; a += kx; final(a, b, c);

    return c; } uint hashInt3(int kx, int ky, int kz) { return hashUint3((uint)kx, (uint)ky, (uint)kz); } float hashUint2ToFloat(uint kx, uint ky) { return float(hashUint2(kx, ky) / float(0xFFFFFFFFu)); } float hashVec2ToFloat(float2 k) { return hashUint2ToFloat(asuint(k.x), asuint(k.y)); } float3 randomVector3Offset(float seed) { return float3(100 + hashVec2ToFloat(float2(seed, 0)) 100, 100 + hashVec2ToFloat(float2(seed, 1)) 100,100 + hashVec2ToFloat(float2(seed, 2)) * 100); } float noiseFbm(float3 co, float detail, float roughness, float lacunarity, int useNormalize) { float3 p = co; float fscale = 1.0; float amp = 1.0; float maxamp = 0.0; float sum = 0.0;

    for (int i = 0; i <= (int)detail; i++)
    {
      float t = safeSnoise(fscale * p);
      sum += t * amp;
      maxamp += amp;
      amp *= roughness;
      fscale *= lacunarity;
    }
    float rmd = frac(detail);
    if (rmd != 0)
    {
      float t = safeSnoise(fscale * p);
      float sum2 = sum + t * amp;
      return (useNormalize == 1) ? lerp(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) : lerp(sum, sum2, rmd);
    }
    else
      return (useNormalize == 1) ? (0.5 * sum / maxamp + 0.5) : sum;

    } };

    //main NoiseFunction nf; float3 color = 0; color.r = nf.noiseFbm(coord, detail, roughness, lacunarity, normalize); color.g = nf.noiseFbm(coord + nf.randomVector3Offset(3.0), detail, roughness, lacunarity, normalize); color.b = nf.noiseFbm(coord + nf.randomVector3Offset(4.0), detail, roughness, lacunarity, normalize); Color = color; return color.r;