diff --git a/src/strands/strands_api.js b/src/strands/strands_api.js index 1dc1602887..3cb832717c 100644 --- a/src/strands/strands_api.js +++ b/src/strands/strands_api.js @@ -110,14 +110,26 @@ export function initGlobalStrandsAPI(p5, fn, strandsContext) { } strandsContext.vertexDeclarations.add(noiseGLSL); strandsContext.fragmentDeclarations.add(noiseGLSL); - // Handle noise(x, y) as noise(vec2) + + // Make each input into a strands node so that we can check their dimensions + const strandsArgs = args.map(arg => p5.strandsNode(arg)); let nodeArgs; - if (args.length === 3) { - nodeArgs = [fn.vec3(args[0], args[1], args[2])]; - } else if (args.length === 2) { - nodeArgs = [fn.vec3(args[0], args[1], 0)]; + if (strandsArgs.length === 3) { + nodeArgs = [fn.vec3(strandsArgs[0], strandsArgs[1], strandsArgs[2])]; + } else if (strandsArgs.length === 2) { + nodeArgs = [fn.vec3(strandsArgs[0], strandsArgs[1], 0)]; + } else if (strandsArgs.length === 1 && strandsArgs[0].dimension <= 3) { + if (strandsArgs[0].dimension === 3) { + nodeArgs = strandsArgs; + } else if (strandsArgs[0].dimension === 2) { + nodeArgs = [fn.vec3(strandsArgs[0], 0)]; + } else { + nodeArgs = [fn.vec3(strandsArgs[0], 0, 0)]; + } } else { - nodeArgs = args; + p5._friendlyError( + `It looks like you've called noise() with ${args.length} arguments. It only supports 1D to 3D input.` + ); } const { id, dimension } = build.functionCallNode(strandsContext, 'noise', nodeArgs, { overloads: [{ diff --git a/test/unit/webgl/p5.Shader.js b/test/unit/webgl/p5.Shader.js index 83b96c7265..17a02acd66 100644 --- a/test/unit/webgl/p5.Shader.js +++ b/test/unit/webgl/p5.Shader.js @@ -1337,5 +1337,67 @@ suite('p5.Shader', function() { assert.isNumber(pixelColor[2]); }); }); + + suite('noise()', () => { + for (let i = 1; i <= 3; i++) { + test(`works with ${i}D vectors`, () => { + expect(() => { + myp5.createCanvas(50, 50, myp5.WEBGL); + const input = new Array(i).fill(10); + const testShader = myp5.baseFilterShader().modify(() => { + myp5.getColor(() => { + return [myp5.noise(input), 0, 0, 1]; + }); + }, { myp5, input }); + myp5.shader(testShader); + myp5.plane(10, 10); + }).not.toThrowError(); + }); + + test(`works with ${i}D positional arguments`, () => { + expect(() => { + myp5.createCanvas(50, 50, myp5.WEBGL); + const input = new Array(i).fill(10); + const testShader = myp5.baseFilterShader().modify(() => { + myp5.getColor(() => { + return [myp5.noise(...input), 0, 0, 1]; + }); + }, { myp5, input }); + myp5.shader(testShader); + myp5.plane(10, 10); + }).not.toThrowError(); + }); + } + + for (const i of [0, 4]) { + test(`Does not work in ${i}D`, () => { + expect(() => { + myp5.createCanvas(50, 50, myp5.WEBGL); + const input = new Array(i).fill(10); + const testShader = myp5.baseFilterShader().modify(() => { + myp5.getColor(() => { + return [myp5.noise(input), 0, 0, 1]; + }); + }, { myp5, input }); + myp5.shader(testShader); + myp5.plane(10, 10); + }).toThrowError(); + }); + + test(`Does not work in ${i}D with positional arguments`, () => { + expect(() => { + myp5.createCanvas(50, 50, myp5.WEBGL); + const input = new Array(i).fill(10); + const testShader = myp5.baseFilterShader().modify(() => { + myp5.getColor(() => { + return [myp5.noise(...input), 0, 0, 1]; + }); + }, { myp5, input }); + myp5.shader(testShader); + myp5.plane(10, 10); + }).toThrowError(); + }); + } + }); }); });