Skip to content

[p5.js 2.0 RFC Proposal]: (Phase 2) R&D to explore GLSL alternatives #7188

@davepagurek

Description

@davepagurek

Increasing access

Writing shaders using just one language (JS, using p5's APIs) rather than leaning a whole new language has the potential to let even more people explore this functionality.

Which types of changes would be made?

  • Breaking change (Add-on libraries or sketches will work differently even if their code stays the same.)
  • Systemic change (Many features or contributor workflows will be affected.)
  • Overdue change (Modifications will be made that have been desirable for a long time.)
  • Unsure (The community can help to determine the type of change.)

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)

What's the problem?

Shaders are one of the most imposing parts of p5 for newcomers. Our existing proposal for shader hooks (#7031) aims to help bridge that gap a bit, but currently one still has to learn a whole new language to start writing shaders. If we can keep everything within the p5 API, there is the potential to make the learning process even easier.

What's the solution?

If we have a p5 function that one can be used to build shader code, then one could use it as anywhere we currently accept a GLSL string without modifying the current API. As a hypothetical example, a shader hook using a GLSL string could look something like the example on the right using a JS-based builder:

Before After
const wiggleShader = materialShader.modify({
  declarations: `uniform float time`,
  getWorldPosition: `(vec3 position) {
    position.y += 10.0 * sin(time * 0.001);
    return position;
  }`
})
const wiggleShader = materialShader.modify((hooks) => {
  const time = createShaderParameter()
  hooks.getWorldPosition = function(position) {
    position.y += 10 * sin(time * 0.001);
    return position
  }
})

In practice, there are a lot of tradeoffs to consider:

  • JavaScript does not support operator overloading, so a pure-JS solution would not be able to handle operations like += and would instead need a more complicated function API
    • Threejs's TSL does this, including function versions of things like If. In a lot of ways, this is also pretty unintuitive since it involves documenting a new set of allowed functions that "replace" native JS constructs like if/else.
    • Another example of this is glsl-autodiff's API, used by p5.warp.
  • Parsing JS source code rather than running it lets you override the + operator, but may confuse users, since variable scope will not work the way they expect, and it disrupts debugging

So this is not a proposal for a feature to immediately implement, but rather, a call for R&D to help narrow down whether or not something like this is actually feasible, and if so, what route to follow.

Pros (updated based on community comments)

  • easier access to shaders as an outlet for creative expression
  • for people who already know shaders, a more flexible way to write them that is less strict about syntax

Cons (updated based on community comments)

  • potentially a lot of work to implement
  • potentially a large added API surface area for people to learn
  • potentially a larger bundle size

Proposal status

Under review

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

Status

Completed

Relationships

None yet

Development

No branches or pull requests

Issue actions