processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.1k stars 3.22k forks source link

[p5.js 2.0 RFC Proposal]: Shader Hooks #7031

Open davepagurek opened 1 month ago

davepagurek commented 1 month ago

Increasing access

Which types of changes would be made?

Most appropriate sub-area of p5.js?

What's the problem?

tl;dr: if you want to write a shader for p5.js, you have to write the whole thing yourself.

What's the solution?

This has been discussed a bit in https://github.com/processing/p5.js/issues/6144#issuecomment-1962677182, but here's a slightly more refined API:

Pros (updated based on community comments)

Cons (updated based on community comments)

Proposal status

Under review

nickmcintyre commented 1 month ago

I'd love to make shaders more accessible to beginners – they're neat. A few questions come to mind:

davepagurek commented 1 month ago

Would these changes complement or impede any other proposed WebGL changes for 2.0?

None so far, but I'll keep this updated if anything new comes up.

Which approach would be easier for a beginner, writing a shader hook in GLSL or transpiling JavaScript to GLSL?

I don't think these are mutually exclusive approaches actually. I think the best case scenario is you have both, as they tackle separate bits of complexity. Hooks address the fact that a shader as a whole entity requires a lot of knowledge about the whole shader pipeline and data flow through it, letting you focus on just one piece at a time for less cognitive load. Js-to-glsl addresses the fact that you also need to know a whole separate language in order to write shaders, which is also additional complexity.

I think the hooks problem is the easier one to tackle first for a few reasons. There are a lot of features in GLSL since it's a whole programming language, so there's just a lot of surface area to cover to be able to write anything you'd want to do in GLSL via JavaScript. I don't think you need full coverage for it to be useful, but if you have the option of writing actual GLSL too, then you've got a nice fallback for edge cases outside of what we cover. I imagine in the future, rather than just writing a GLSL string, you'd call some p5 methods that at also support .toString() to turn it to GLSL so that you could swap out anything that's currently a string for a js-to-glsl implementation of some kind. The other current concern is just that it has the potential to add a lot of code, so it might be good to defer that bit to after we've done some initial work on figuring out how to handle optional dependencies to not increase the core bundle size, so that we have some best practices to follow.

One other point I'll mention is that we've put more time thinking about the API for hooks already, and probably the riskiest part was the API planning so that we make something we can support going forward. We haven't done that thinking and de-risking yet for js-to-glsl, so that will add to its development time. Definitely something to start thinking about, but I think probably not actionable yet in the near term for 2.0.

What's a rough estimate for the effort needed to implement shader hooks? How about JS-to-GLSL?

I have a functional prototype with a slightly less refined interface, where it probably is only a day or two of development to get the API to match the proposal. The longer chunk of work, I think, will be documenting all the hooks added into the core shaders. I think it's also OK for that to grow over time, maybe only needing examples for the most useful hooks, and just documenting the types + a description for the other ones at first. I'd like to spend maybe a week getting those high priority ones looking good, and then we could ask for community help on adding to the rest.

For a js-to-glsl project, I think it'll take a bit of R&D at first. There are a lot of different approaches one could take that all have different tradeoffs. A Shader Park style system has you write what looks like a real js function, which it then reads as a source code string, parses, and recompiles. You could also go for a p5.Vector (and p5.warp) like system that makes js function calls to generate objects that track the operations and then generate source code from that. You'd maybe need to look into both more closely and figure out the size/flexibility tradeoffs, and then work from there. That to me sounds like a fairly large project, maybe GSoC sized on the order of months.

Can this feature start as an addon library or does it require significant modifications to the p5.js core?

You could make something like this outside of core p5 and it would work, but it means that the shaders go out of date whenever core p5 changes, and the addon is responsible for copy and pasting source code whenever the p5 source changes. That's currently what p5.warp does, and it means the library breaks slightly with every new version.

One of the reason why I think hooks would be the part to do in 2.0 rather than js-to-glsl is that I think js-to-glsl is maybe a better fit for an addon. As long as core accepts a glsl string, then that's an interchange format between core and the addon that the addon can build for, and since GLSL will not be changing like p5 does, it doesn't have the same problems with going out of date.