From d6310a6ed59091bc64780164fd6304ea945cf762 Mon Sep 17 00:00:00 2001 From: Lalit Narayan Yadav <162928571+LalitNarayanYadav@users.noreply.github.com> Date: Sat, 19 Jul 2025 22:40:14 +0530 Subject: [PATCH 1/2] Add 3D noise(vec3) support to p5.strands --- src/webgl/ShaderGenerator.js | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/webgl/ShaderGenerator.js b/src/webgl/ShaderGenerator.js index 58b3c7cc34..4b1a495424 100644 --- a/src/webgl/ShaderGenerator.js +++ b/src/webgl/ShaderGenerator.js @@ -8,6 +8,7 @@ import { parse } from 'acorn'; import { ancestor } from 'acorn-walk'; import escodegen from 'escodegen'; import noiseGLSL from './shaders/functions/noiseGLSL.glsl'; +import noise3DGLSL from './shaders/functions/noise3DGLSL.glsl'; function shadergenerator(p5, fn) { @@ -1663,23 +1664,34 @@ function shadergenerator(p5, fn) { const originalNoise = fn.noise; fn.noise = function (...args) { if (!GLOBAL_SHADER?.isGenerating) { - return originalNoise.apply(this, args); // fallback to regular p5.js noise + return originalNoise.apply(this, args); // fallback to p5.js noise } - - GLOBAL_SHADER.output.vertexDeclarations.add(noiseGLSL); - GLOBAL_SHADER.output.fragmentDeclarations.add(noiseGLSL); - // Handle noise(x, y) as noise(vec2) + let nodeArgs; - if (args.length === 2) { + + if (args.length === 3) { + // GLSL vec3 noise(x, y, z) + nodeArgs = [fn.vec3(args[0], args[1], args[2])]; + GLOBAL_SHADER.output.vertexDeclarations.add(noise3DGLSL); + GLOBAL_SHADER.output.fragmentDeclarations.add(noise3DGLSL); + + return fnNodeConstructor('noise', nodeArgs, { + args: ['vec3'], + returnType: 'float', + }); + } else if (args.length === 2) { + // GLSL vec2 noise(x, y) nodeArgs = [fn.vec2(args[0], args[1])]; - } else { - nodeArgs = args; + GLOBAL_SHADER.output.vertexDeclarations.add(noiseGLSL); + GLOBAL_SHADER.output.fragmentDeclarations.add(noiseGLSL); + + return fnNodeConstructor('noise', nodeArgs, { + args: ['vec2'], + returnType: 'float', + }); } - return fnNodeConstructor('noise', nodeArgs, { - args: ['vec2'], - returnType: 'float' - }); + return originalNoise.apply(this, args); // fallback again if unexpected }; } From 738fc3faae7a4d4482c7a99d00d6a3bf54796dc9 Mon Sep 17 00:00:00 2001 From: Lalit Narayan Yadav <162928571+LalitNarayanYadav@users.noreply.github.com> Date: Sat, 19 Jul 2025 22:43:59 +0530 Subject: [PATCH 2/2] Create noise3DGLSL.glsl to add 3D noise(vec3) support to p5.strands --- src/webgl/shaders/functions/noise3DGLSL.glsl | 52 ++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/webgl/shaders/functions/noise3DGLSL.glsl diff --git a/src/webgl/shaders/functions/noise3DGLSL.glsl b/src/webgl/shaders/functions/noise3DGLSL.glsl new file mode 100644 index 0000000000..2eb92e2d89 --- /dev/null +++ b/src/webgl/shaders/functions/noise3DGLSL.glsl @@ -0,0 +1,52 @@ +// Based on https://thebookofshaders.com/13/ and https://github.com/patriciogonzalezvivo/lygia +// MIT licensed, adapted for p5.strands + +vec3 random3(vec3 p) { + return fract(sin(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)) + )) * 43758.5453123); +} + +float baseNoise(vec3 p) { + vec3 i = floor(p); + vec3 f = fract(p); + + // Compute corner vectors + vec3 a = random3(i); + vec3 b = random3(i + vec3(1, 0, 0)); + vec3 c = random3(i + vec3(0, 1, 0)); + vec3 d = random3(i + vec3(1, 1, 0)); + vec3 e = random3(i + vec3(0, 0, 1)); + vec3 f1 = random3(i + vec3(1, 0, 1)); + vec3 g = random3(i + vec3(0, 1, 1)); + vec3 h = random3(i + vec3(1, 1, 1)); + + vec3 u = f * f * (3.0 - 2.0 * f); + + return mix( + mix( + mix(dot(a, f - vec3(0, 0, 0)), dot(b, f - vec3(1, 0, 0)), u.x), + mix(dot(c, f - vec3(0, 1, 0)), dot(d, f - vec3(1, 1, 0)), u.x), u.y + ), + mix( + mix(dot(e, f - vec3(0, 0, 1)), dot(f1, f - vec3(1, 0, 1)), u.x), + mix(dot(g, f - vec3(0, 1, 1)), dot(h, f - vec3(1, 1, 1)), u.x), u.y + ), + u.z + ); +} + +float noise(vec3 p) { + float result = 0.0; + float amplitude = 1.0; + float frequency = 1.0; + + for (int i = 0; i < 4; i++) { + result += amplitude * baseNoise(p * frequency); + frequency *= 2.0; + amplitude *= 0.5; + } + return result; +}