Description
Increasing access
Make p5.strands more intuitive.
Most appropriate sub-area of p5.js?
- Accessibility
- Color
- Core/Environment/Rendering
- Data
- DOM
- Events
- Image
- IO
- Math
- Typography
- Utilities
- WebGL
- Build process
- Unit testing
- Internationalization
- Friendly errors
- Other (specify if possible)
Feature enhancement details
From the original Discord discussion:
Orcé:
Hi there!
I'm going through the strands introduction. First off, let me say that p5.strands is an awesome idea and a huge improvement on the previous ways of using GLSL with p5.js.
That said, I'm running into issues with creating reusable functions for strands.Looking at this example from the intro:
function instancingCallback() {
// a pseudorandom function from:
// https://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl
function rand(seed) {
return fract(sin(dot(seed, [12.9898, 78.233])) * 43758.5453123);
}fract(sin(dot(seed, [12.9898, 78.233])) * 43758.5453123); seems like a very useful function to put in a utils library. I'm probably going to use it over and over again. However, defining a rand() funtion elsewhere and trying to call it within the callback sends an error:
Uncaught (in promise) TypeError: Failed to execute 'useProgram' on 'WebGL2RenderingContext': parameter 1 is not of type 'WebGLProgram'.
I assume this is because the code within the callback gets transpiled to GLSL without resolving the reference to the rand() function?Before I embark into some metaprogramming shenanigans, is there a recommended way to extend p5.strands? Is there a prototype somewhere on which we can define additional functions etc?
I apologize if this is in the doc somewhere, couldn't find anything about this topic.
dave:
hey! so currently there isn't exactly. I'll go into why briefly in order to explain how a workaround for now could work, and how we can then make this a real thing in the future.
So in JavaScript, you can't actually do a + operator between anything but strings and numbers. In order to do it for vectors, we actually have to rewrite your js for you. if you put a debugger statement in your random function, and then run your code with the debugger open, you'll notice the code looks a little different. First, instead of square brackets making a vector, it uses a vector constructor. Second, operators like the multiplication operator turn into a method on the vector, like .mult(). We only rewrite the code in your callback function, which is why currently it doesn't work when you extract it into another file.
So a potential workaround for now is to write your helper function the way it would look without any of those shortcuts that we rewrite (so, using vec2(a,b) instead of [a,b], and using methods like .mult instead of the * operator.)
But as you've noticed this is pretty unintuitive so it would be great to have a real way to do this! Some thoughts:
We're adding some common things like random and noise into p5 core (e.g. #7921) If something is common enough, it could be worth adding for everyone in this way.
We could let you explicitly define strands helpers. We could make a function like rand = strandsHelper(function() { ... }) that applies the preprocessing to your helper even though it doesn't live inside your callback.
More effort, but we could detect calls to external functions in your callback and rewrite them too. This would have to be recursive (those functions could call other functions) and might mean having to deal with scope issues. So it's harder for us, but could mean everything just works for users without having to change anything.