diff --git a/README.md b/README.md index 6bbc47f..2c2672c 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,13 @@ Please consider sponsoring me if you enjoy the results of my work, code or docum ## UPDATES +**2025/06/16** @1.1.37: +* overhaul of perlin noise +* batch processing moved to fore-front +* speed attribute for noise +* noise offset changed to vec2 for 2d noise +* batch attribute moved to bottom of noises + **2025/05/16** @1.1.36: * updated to comfy_cozy 0.0.25 diff --git a/core/glsl.py b/core/glsl.py index cb0b9e6..6076104 100644 --- a/core/glsl.py +++ b/core/glsl.py @@ -126,7 +126,7 @@ class GLSLNodeDynamic(CozyImageNode): CONTROL = [] PARAM = [] - # res, frame. framerate, time, batch, matte, edge, batch, seed + # res, frame. framerate, time, matte, edge, seed, batch @classmethod def INPUT_TYPES(cls) -> dict: @@ -157,12 +157,6 @@ class GLSLNodeDynamic(CozyImageNode): "tooltip": "Value to use directly; if > -1 will override iFrame/iFrameRate calculation." }) - if 'BATCH' in cls.CONTROL: - optional["batch"] = ("INT", { - "default": 1, "min": 1, "max": sys.maxsize, - "tooltip": "Number of frames to generate. 0 (continuous mode) means continue from the last queue generating the next single frame based on iFrameRate. In the shader this will be the index of the batch iteration or 0." - }) - if 'MATTE' in cls.CONTROL: optional["matte"] = ("VEC4", { "default": (0, 0, 0, 255), @@ -197,6 +191,12 @@ class GLSLNodeDynamic(CozyImageNode): "tooltip": "Number of frames to generate. 0 (continuous mode) means continue from the last queue generating the next single frame based on iFrameRate." }) + if 'BATCH' in cls.CONTROL: + optional["batch"] = ("INT", { + "default": 1, "min": 1, "max": sys.maxsize, + "tooltip": "Number of frames to generate. 0 (continuous mode) means continue from the last queue generating the next single frame based on iFrameRate. In the shader this will be the index of the batch iteration or 0." + }) + """ 'MODE': (EnumScaleMode._member_names_, {"default": EnumScaleMode.MATTE.name}) 'SAMPLE': (EnumInterpolation._member_names_, {"default": EnumInterpolation.LANCZOS4.name}) @@ -277,7 +277,7 @@ class GLSLNodeDynamic(CozyImageNode): self.__glsl = None def run(self, ident, **kw) -> RGBAMaskType: - # IRES, MATTE, EDGE, IFRAME, IFRAMERATE, ITIME, BATCH, SEED + # IRES, MATTE, EDGE, IFRAME, IFRAMERATE, ITIME, SEED, BATCH iResolution = parse_param(kw, 'iRes', EnumConvertType.VEC2INT, [(IMAGE_SIZE_DEFAULT, IMAGE_SIZE_DEFAULT)], IMAGE_SIZE_MIN, IMAGE_SIZE_MAX) diff --git a/glsl/.lib/noise/noise_blue.lib b/glsl/.lib/noise/noise_blue.lib index 5f6f2aa..a84d70c 100644 --- a/glsl/.lib/noise/noise_blue.lib +++ b/glsl/.lib/noise/noise_blue.lib @@ -8,11 +8,11 @@ //------------------------------------------------------------------------------ // Generate high-quality blue noise -float noise_blue(vec2 uv int seed) { +float noise_blue(vec2 uv uint seed) { vec3 p = vec3(uv, 0.0); float t = fract(0.0); - vec3 n1 = noise_hash3(floor(p), seed); - vec3 n2 = noise_hash3(ceil(p), seed); + vec3 n1 = noise_hash(floor(p), seed); + vec3 n2 = noise_hash(ceil(p), seed); return mix(n1.x, n2.x, smoothstep(0.0, 1.0, t)); } diff --git a/glsl/.lib/noise/noise_grad.lib b/glsl/.lib/noise/noise_grad.lib index 9243d4f..92b07af 100644 --- a/glsl/.lib/noise/noise_grad.lib +++ b/glsl/.lib/noise/noise_grad.lib @@ -2,7 +2,7 @@ #define LIB_NOISE_GRAD //------------------------------------------------------------------------------ -// GRADIENT COMPUTATION +// GRADIENT (GENERIC) // Core gradient calculation functions used by noise algorithms //------------------------------------------------------------------------------ @@ -15,4 +15,38 @@ GRAD(vec2) GRAD(vec3) GRAD(vec4) +//------------------------------------------------------------------------------ +// GRADIENT +// Core gradient calculation functions used by noise algorithms +//------------------------------------------------------------------------------ + +vec2 gradient2D(vec2 h) { + // Convert [0,1] -> angle in radians + float angle = 6.2831853 * fract(h.x + h.y); + return vec2(cos(angle), sin(angle)); +} + +vec3 gradient3D(vec3 h) { + float theta = 6.2831853 * h.x; + float phi = acos(2.0 * h.y - 1.0); + return vec3( + sin(phi) * cos(theta), + sin(phi) * sin(theta), + cos(phi) + ); +} + +vec4 gradient4D(vec4 h) { + float theta1 = 6.2831853 * h.x; + float theta2 = 6.2831853 * h.y; + float r1 = sqrt(1.0 - h.z); + float r2 = sqrt(h.z); + return vec4( + r1 * cos(theta1), + r1 * sin(theta1), + r2 * cos(theta2), + r2 * sin(theta2) + ); +} + #endif \ No newline at end of file diff --git a/glsl/.lib/noise/noise_hash.lib b/glsl/.lib/noise/noise_hash.lib index 5035169..7260cfb 100644 --- a/glsl/.lib/noise/noise_hash.lib +++ b/glsl/.lib/noise/noise_hash.lib @@ -1,337 +1,51 @@ #ifndef LIB_NOISE_HASH #define LIB_NOISE_HASH -//------------------------------------------------------------------------------ -// SUPPORT -//------------------------------------------------------------------------------ - -uvec2 floatToBits(vec2 v) { - return uvec2(floatBitsToUint(v.x), floatBitsToUint(v.y)); -} - -uvec3 floatToBits(vec3 v) { - return uvec3(floatBitsToUint(v.x), floatBitsToUint(v.y), floatBitsToUint(v.z)); -} - -uvec4 floatToBits(vec4 v) { - return uvec4(floatBitsToUint(v.x), floatBitsToUint(v.y), floatBitsToUint(v.z), floatBitsToUint(v.w)); -} - //------------------------------------------------------------------------------ // HASH NOISE //------------------------------------------------------------------------------ -uint hashMurmur_11(uint src, uint seed) { - const uint M = 0x5bd1e995u; - uint h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} +vec2 noise_hash(vec2 p, uint seed) { + // Base fract transform on position only + vec3 p3 = fract(vec3(p.xyx) * 0.1031); -// 1 output, 1 input -float hash11(float src, uint seed) { - uint h = hashMurmur_11(floatBitsToUint(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} + // Mix in seed parts scaled down to small floats for precision-safe entropy injection + float seedA = float((seed & 0xFFu)) * 0.0001; + float seedB = float(((seed >> 8) & 0xFFu)) * 0.0007; + float seedC = float(((seed >> 16) & 0xFFu)) * 0.0003; -//------------------------------------------------------------------------------ - -uint hashMurmur_12(uvec2 src, uint seed) { - const uint M = 0x5bd1e995u; - uint h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 1 output, 2 inputs -float hash12(vec2 src, uint seed) { - uint h = hashMurmur_12(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uint hashMurmur_13(uvec3 src, uint seed) { - const uint M = 0x5bd1e995u; - uint h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; h *= M; h ^= src.z; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 1 output, 3 inputs -float hash13(vec3 src, uint seed) { - uint h = hashMurmur_13(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uint hashMurmur_14(uvec4 src, uint seed) { - const uint M = 0x5bd1e995u; - uint h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; h *= M; h ^= src.z; h *= M; h ^= src.w; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 1 output, 4 inputs -float hash14(vec4 src, uint seed) { - uint h = hashMurmur_14(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec2 hashMurmur_21(uint src, uvec2 seed) { - const uint M = 0x5bd1e995u; - uvec2 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 2 outputs, 1 input -vec2 hash21(float src, uvec2 seed) { - uvec2 h = hashMurmur_21(floatBitsToUint(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec2 hashMurmur_22(uvec2 src, uvec2 seed) { - const uint M = 0x5bd1e995u; - uvec2 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 2 outputs, 2 inputs -vec2 hash22(vec2 src, uvec2 seed) { - uvec2 h = hashMurmur_22(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec2 hashMurmur_23(uvec3 src, uvec2 seed) { - const uint M = 0x5bd1e995u; - uvec2 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; h *= M; h ^= src.z; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 2 outputs, 3 inputs -vec2 hash23(vec3 src, uvec2 seed) { - uvec2 h = hashMurmur_23(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec2 hashMurmur_24(uvec4 src, uvec2 seed) { - const uint M = 0x5bd1e995u; - uvec2 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; h *= M; h ^= src.z; h *= M; h ^= src.w; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 2 outputs, 4 inputs -vec2 hash24(vec4 src, uvec2 seed) { - uvec2 h = hashMurmur_24(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec3 hashMurmur_31(uint src, uvec3 seed) { - const uint M = 0x5bd1e995u; - uvec3 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 3 outputs, 1 input -vec3 hash31(float src, uvec3 seed) { - uvec3 h = hashMurmur_31(floatBitsToUint(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec3 hashMurmur_32(uvec2 src, uvec3 seed) { - const uint M = 0x5bd1e995u; - uvec3 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 3 outputs, 2 inputs -vec3 hash32(vec2 src, uvec3 seed) { - uvec3 h = hashMurmur_32(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec3 hashMurmur_33(uvec3 src, uvec3 seed) { - const uint M = 0x5bd1e995u; - uvec3 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; h *= M; h ^= src.z; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 3 outputs, 3 inputs -vec3 hash33(vec3 src, uvec3 seed) { - uvec3 h = hashMurmur_33(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec3 hashMurmur_34(uvec4 src, uvec3 seed) { - const uint M = 0x5bd1e995u; - uvec3 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; h *= M; h ^= src.z; h *= M; h ^= src.w; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 3 outputs, 4 inputs -vec3 hash34(vec4 src, uvec3 seed) { - uvec3 h = hashMurmur_34(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec4 hashMurmur_41(uint src, uvec4 seed) { - const uint M = 0x5bd1e995u; - uvec4 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 4 outputs, 1 input -vec4 hash41(float src, uvec4 seed) { - uvec4 h = hashMurmur_41(floatBitsToUint(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec4 hashMurmur_42(uvec2 src, uvec4 seed) { - const uint M = 0x5bd1e995u; - uvec4 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 4 outputs, 2 inputs -vec4 hash42(vec2 src, uvec4 seed) { - uvec4 h = hashMurmur_42(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec4 hashMurmur_43(uvec3 src, uvec4 seed) { - const uint M = 0x5bd1e995u; - uvec4 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; h *= M; h ^= src.z; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 4 outputs, 3 inputs -vec4 hash43(vec3 src, uvec4 seed) { - uvec4 h = hashMurmur_43(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ - -uvec4 hashMurmur_44(uvec4 src, uvec4 seed) { - const uint M = 0x5bd1e995u; - uvec4 h = seed; - src *= M; src ^= src>>24u; src *= M; - h *= M; h ^= src.x; h *= M; h ^= src.y; h *= M; h ^= src.z; h *= M; h ^= src.w; - h ^= h>>13u; h *= M; h ^= h>>15u; - return h; -} - -// 4 outputs, 4 inputs -vec4 hash44(vec4 src, uvec4 seed) { - uvec4 h = hashMurmur_44(floatToBits(src), seed); - return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0; -} - -//------------------------------------------------------------------------------ -// STANDARD HASH NOISE -//------------------------------------------------------------------------------ - -float noise_hash(int n) { - n = (n << 13) ^ n; - return float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 0x7fffffff; -} - -// Basic 1D hash - maps float to float [0,1] -float noise_hash11(float p) { - p = fract(p * .1031); - p *= p + 33.33; - return fract(p * p); -} - -// 2D to 1D hash - maps vec2 to float [0,1] -float noise_hash21(vec2 p) { - vec3 p3 = fract(vec3(p.xyx) * .1031); + p3 += seedA + seedB + seedC; p3 += dot(p3, p3.yzx + 33.33); - return fract((p3.x + p3.y) * p3.z); + + return fract(vec2(p3.x + p3.y, p3.y + p3.z)); } -// 3D to 3D hash - maps vec3 to vec3 [0,1] -vec3 noise_hash33(vec3 p) { - p = fract(p * vec3(443.8975, 397.2973, 491.1871)); - p += dot(p.zxy, p.yxz + 19.19); - return fract(vec3(p.x * p.y, p.y * p.z, p.z * p.x)); +vec3 noise_hash(vec3 p, uint seed) { + p = fract(p * 0.1031); + + float seedA = float((seed & 0xFFu)) * 0.0001; + float seedB = float(((seed >> 8) & 0xFFu)) * 0.0007; + float seedC = float(((seed >> 16) & 0xFFu)) * 0.0003; + + p += seedA + seedB + seedC; + p += dot(p, p.yzx + 33.33); + + return fract((p.xxy + p.yzz) * p.zyx); } -vec3 noise_hash33_2(vec3 p) { - p = vec3( dot(p,vec3(127.1,311.7, 74.7)), - dot(p,vec3(269.5,183.3,246.1)), - dot(p,vec3(113.5,271.9,124.6))); - return fract(sin(p)*43758.5453123); +vec4 noise_hash(vec4 p, uint seed) { + p = fract(p * 0.1031); + + float seedA = float((seed & 0xFFu)) * 0.0001; + float seedB = float(((seed >> 8) & 0xFFu)) * 0.0007; + float seedC = float(((seed >> 16) & 0xFFu)) * 0.0003; + float seedD = float(((seed >> 24) & 0xFFu)) * 0.0005; + + p += seedA + seedB + seedC + seedD; + p += dot(p, p.wzxy + 33.33); + + return fract((p.xxyz + p.yzzw) * p.wzyx); } -vec3 noise_hash33_3(vec3 p3) { - p3 = fract(p3 * vec3(10.31, 10.3, 9.73)); - p3 += dot(p3, p3.yxz+33.33); - return fract((p3.xxy + p3.yxx)*p3.zyx); -} #endif diff --git a/glsl/.lib/noise/noise_perlin.lib b/glsl/.lib/noise/noise_perlin.lib index 6805b3b..c47bf5a 100644 --- a/glsl/.lib/noise/noise_perlin.lib +++ b/glsl/.lib/noise/noise_perlin.lib @@ -2,118 +2,94 @@ #define LIB_NOISE_PERLIN #include .lib/noise/noise_hash.lib +#include .lib/noise/noise_grad.lib #include .lib/noise/noise_param.lib //------------------------------------------------------------------------------ // NOISE PERLIN //------------------------------------------------------------------------------ -vec2 gradient2D(uint hash) { - switch (int(hash) & 7) { - case 0: return vec2(1, 0); - case 1: return vec2(-1, 0); - case 2: return vec2(0, 1); - case 3: return vec2(0, -1); - case 4: return normalize(vec2(1, 1)); - case 5: return normalize(vec2(-1, 1)); - case 6: return normalize(vec2(1, -1)); - case 7: return normalize(vec2(-1, -1)); - default: return vec2(0); - } -} - -vec3 gradient3D(uint hash) { - // look at the last four bits to pick a gradient direction - switch (int(hash) & 15) { - case 0: return vec3(1, 1, 0); - case 1: return vec3(-1, 1, 0); - case 2: return vec3(1, -1, 0); - case 3: return vec3(-1, -1, 0); - case 4: return vec3(1, 0, 1); - case 5: return vec3(-1, 0, 1); - case 6: return vec3(1, 0, -1); - case 7: return vec3(-1, 0, -1); - case 8: return vec3(0, 1, 1); - case 9: return vec3(0, -1, 1); - case 10: return vec3(0, 1, -1); - case 11: return vec3(0, -1, -1); - case 12: return vec3(1, 1, 0); - case 13: return vec3(-1, 1, 0); - case 14: return vec3(0, -1, 1); - case 15: return vec3(0, -1, -1); - default: return vec2(0); - } -} - -vec4 gradient4D(uint hash) { - int h = int(hash) & 31; - return normalize(vec4( - ((h & 1) == 0) ? 1.0 : -1.0, - ((h & 2) == 0) ? 1.0 : -1.0, - ((h & 4) == 0) ? 1.0 : -1.0, - ((h & 8) == 0) ? 1.0 : -1.0 - )); -} - // Generate 2D Perlin noise float noise_perlin(vec2 p, uint seed) { vec2 i = floor(p); vec2 f = p - i; - uvec2 cellSeed = uvec2(seed); - float a = dot(gradient2D(hash22(i, cellSeed)), f); - float b = dot(gradient2D(hash22((i + vec2(1., 0.)), cellSeed)), f - vec2(1., 0.)); - float c = dot(gradient2D(hash22((i + vec2(0., 1.)), cellSeed)), f - vec2(0., 1.)); - float d = dot(gradient2D(hash22((i + vec2(1., 1.)), cellSeed)), f - vec2(1., 1.)); + float a = dot(gradient2D(noise_hash(i, seed)), f); + float b = dot(gradient2D(noise_hash((i + vec2(1., 0.)), seed)), f - vec2(1., 0.)); + float c = dot(gradient2D(noise_hash((i + vec2(0., 1.)), seed)), f - vec2(0., 1.)); + float d = dot(gradient2D(noise_hash((i + vec2(1., 1.)), seed)), f - vec2(1., 1.)); - vec2 u = smoothstep(0., 1., f); + //vec2 u = smoothstep(0., 1., f); + vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0); return mix(mix(a, b, u.x), mix(c, d, u.x), u.y); } -// 3D Perlin Noise function float noise_perlin(vec3 p, uint seed) { vec3 i = floor(p); vec3 f = p - i; - uvec3 cellSeed = uvec3(seed); - float a = dot(gradient3D(hash33(i, cellSeed)), f); - float b = dot(gradient3D(hash33((i + vec3(1., 0., 0.)), cellSeed)), f - vec3(1., 0., 0.)); - float c = dot(gradient3D(hash33((i + vec3(0., 1., 0.)), cellSeed)), f - vec3(0., 1., 0.)); - float d = dot(gradient3D(hash33((i + vec3(1., 1., 0.)), cellSeed)), f - vec3(1., 1., 0.)); - float e = dot(gradient3D(hash33((i + vec3(0., 0., 1.)), cellSeed)), f - vec3(0., 0., 1.)); - float f0 = dot(gradient3D(hash33((i + vec3(1., 0., 1.)), cellSeed)), f - vec3(1., 0., 1.)); - float g0 = dot(gradient3D(hash33((i + vec3(0., 1., 1.)), cellSeed)), f - vec3(0., 1., 1.)); - float h0 = dot(gradient3D(hash33((i + vec3(1., 1., 1.)), cellSeed)), f - vec3(1., 1., 1.)); + float n000 = dot(gradient3D(noise_hash(i + vec3(0, 0, 0), seed)), f - vec3(0, 0, 0)); + float n100 = dot(gradient3D(noise_hash(i + vec3(1, 0, 0), seed)), f - vec3(1, 0, 0)); + float n010 = dot(gradient3D(noise_hash(i + vec3(0, 1, 0), seed)), f - vec3(0, 1, 0)); + float n110 = dot(gradient3D(noise_hash(i + vec3(1, 1, 0), seed)), f - vec3(1, 1, 0)); + float n001 = dot(gradient3D(noise_hash(i + vec3(0, 0, 1), seed)), f - vec3(0, 0, 1)); + float n101 = dot(gradient3D(noise_hash(i + vec3(1, 0, 1), seed)), f - vec3(1, 0, 1)); + float n011 = dot(gradient3D(noise_hash(i + vec3(0, 1, 1), seed)), f - vec3(0, 1, 1)); + float n111 = dot(gradient3D(noise_hash(i + vec3(1, 1, 1), seed)), f - vec3(1, 1, 1)); - vec3 u = smoothstep(0., 1., f); - return mix(mix(mix(a, b, u.x), mix(c, d, u.x), u.y), mix(mix(e, f0, u.x), mix(g0, h0, u.x), u.y), u.z); + vec3 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0); + + return mix( + mix(mix(n000, n100, u.x), mix(n010, n110, u.x), u.y), + mix(mix(n001, n101, u.x), mix(n011, n111, u.x), u.y), + u.z + ); } -// 4D Perlin Noise function float noise_perlin(vec4 p, uint seed) { vec4 i = floor(p); vec4 f = p - i; - uvec4 cellSeed = uvec4(seed); - float a = dot(gradient4D(hash44(i, cellSeed)), f); - float b = dot(gradient4D(hash44((i + vec4(1, 0, 0, 0)), cellSeed)), f - vec4(1., 0., 0., 0.)); - float c = dot(gradient4D(hash44((i + vec4(0, 1, 0, 0)), cellSeed)), f - vec4(0., 1., 0., 0.)); - float d = dot(gradient4D(hash44((i + vec4(1, 1, 0, 0)), cellSeed)), f - vec4(1., 1., 0., 0.)); - float e = dot(gradient4D(hash44((i + vec4(0, 0, 1, 0)), cellSeed)), f - vec4(0., 0., 1., 0.)); - float f0 = dot(gradient4D(hash44((i + vec4(1, 0, 1, 0)), cellSeed)), f - vec4(1., 0., 1., 0.)); - float g0 = dot(gradient4D(hash44((i + vec4(0, 1, 1, 0)), cellSeed)), f - vec4(0., 1., 1., 0.)); - float h0 = dot(gradient4D(hash44((i + vec4(1, 1, 1, 0)), cellSeed)), f - vec4(1., 1., 1., 0.)); - float i1 = dot(gradient4D(hash44((i + vec4(0, 0, 0, 1)), cellSeed)), f - vec4(0., 0., 0., 1.)); - float j1 = dot(gradient4D(hash44((i + vec4(1, 0, 0, 1)), cellSeed)), f - vec4(1., 0., 0., 1.)); - float k1 = dot(gradient4D(hash44((i + vec4(0, 1, 0, 1)), cellSeed)), f - vec4(0., 1., 0., 1.)); - float l1 = dot(gradient4D(hash44((i + vec4(1, 1, 0, 1)), cellSeed)), f - vec4(1., 1., 0., 1.)); - float m1 = dot(gradient4D(hash44((i + vec4(0, 0, 1, 1)), cellSeed)), f - vec4(0., 0., 1., 1.)); - float n1 = dot(gradient4D(hash44((i + vec4(1, 0, 1, 1)), cellSeed)), f - vec4(1., 0., 1., 1.)); - float o1 = dot(gradient4D(hash44((i + vec4(0, 1, 1, 1)), cellSeed)), f - vec4(0., 1., 1., 1.)); - float p1 = dot(gradient4D(hash44((i + vec4(1, 1, 1, 1)), cellSeed)), f - vec4(1., 1., 1., 1.)); + #define DOT(off) dot(gradient4D(noise_hash(i + off, seed)), f - off) - vec3 u = smoothstep(0., 1., f); - return mix(mix(mix(a, b, u.x), mix(c, d, u.x), u.y), mix(mix(e, f0, u.x), mix(g0, h0, u.x), u.y), u.z); + float n0000 = DOT(vec4(0, 0, 0, 0)); + float n1000 = DOT(vec4(1, 0, 0, 0)); + float n0100 = DOT(vec4(0, 1, 0, 0)); + float n1100 = DOT(vec4(1, 1, 0, 0)); + float n0010 = DOT(vec4(0, 0, 1, 0)); + float n1010 = DOT(vec4(1, 0, 1, 0)); + float n0110 = DOT(vec4(0, 1, 1, 0)); + float n1110 = DOT(vec4(1, 1, 1, 0)); + + float n0001 = DOT(vec4(0, 0, 0, 1)); + float n1001 = DOT(vec4(1, 0, 0, 1)); + float n0101 = DOT(vec4(0, 1, 0, 1)); + float n1101 = DOT(vec4(1, 1, 0, 1)); + float n0011 = DOT(vec4(0, 0, 1, 1)); + float n1011 = DOT(vec4(1, 0, 1, 1)); + float n0111 = DOT(vec4(0, 1, 1, 1)); + float n1111 = DOT(vec4(1, 1, 1, 1)); + + vec4 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0); + + float x00 = mix(n0000, n1000, u.x); + float x10 = mix(n0100, n1100, u.x); + float x01 = mix(n0010, n1010, u.x); + float x11 = mix(n0110, n1110, u.x); + float x00_1 = mix(n0001, n1001, u.x); + float x10_1 = mix(n0101, n1101, u.x); + float x01_1 = mix(n0011, n1011, u.x); + float x11_1 = mix(n0111, n1111, u.x); + + float y0 = mix(x00, x10, u.y); + float y1 = mix(x01, x11, u.y); + float y0_1 = mix(x00_1, x10_1, u.y); + float y1_1 = mix(x01_1, x11_1, u.y); + + float z0 = mix(y0, y1, u.z); + float z1 = mix(y0_1, y1_1, u.z); + + return mix(z0, z1, u.w); } //------------------------------------------------------------------------------ diff --git a/glsl/.lib/noise/noise_space_cosmic.lib b/glsl/.lib/noise/noise_space_cosmic.lib index 52fb28d..27d00b1 100644 --- a/glsl/.lib/noise/noise_space_cosmic.lib +++ b/glsl/.lib/noise/noise_space_cosmic.lib @@ -16,7 +16,7 @@ float noise_cosmicWeb(vec2 p, float scale) { for(int y = -1; y <= 1; y++) { for(int x = -1; x <= 1; x++) { vec2 offset = vec2(x, y); - vec2 pos = offset + noise_hash33(vec3(id + offset, 0.0)).xy; + vec2 pos = offset + noise_hash(vec3(id + offset, 0.0)).xy; min_dist = min(min_dist, length(f - pos)); } } diff --git a/node_list.json b/node_list.json index 2184e7b..4236999 100644 --- a/node_list.json +++ b/node_list.json @@ -12,9 +12,9 @@ "INVERT (JOV_GL)": "Invert the channels of an image along a scalar [0", "LINEAR GRADIENT (JOV_GL)": "Generate a two color linear gradient", "MIN MAX (JOV_GL)": "Gets the minimum and maximum of an image", - "NOISE PERLIN (JOV_GL)": "Classic Perlin noise", - "NOISE SIMPLEX (JOV_GL)": "Simplex noise, simply", - "NOISE WORLEY (JOV_GL)": "Worley noise with the best", + "NOISE PERLIN (JOV_GL)": "Classic Perlin noise with batch output", + "NOISE SIMPLEX (JOV_GL)": "Simplex noise with batch output", + "NOISE WORLEY (JOV_GL)": "Worley (cellular) noise with batch output", "NORMAL (JOV_GL)": "Convert input into a Normal map", "NORMAL BLEND (JOV_GL)": "Blend two Normal maps", "PIXELATE (JOV_GL)": "Pixelate input image",