processing / processing/p5.js

[p5.strands]: Abstract away `varying` and allow passing data between hooks in the same shader stage

Open
#7,995 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Enhancement p5.strands
Dominant language
JavaScript
Stars
24k
Forks
3.8k
Avg merge
3d 16h
Merged PRs (30d)
25

Description

Increasing access

Currently there isn't a way in p5.strands to pass data between one hook in e.g. the vertex shader and another hook in the vertex shader. You can do it between vertex/fragment with a varying, but this requires users to Just Know which is which, but this is not documented anywhere, and is a new concept for them to learn. It seems feasible that we could do all this for you under the hood to reduce the incoming knowledge users have to have to be able to use p5.strands.

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

Currently, you can pass variables between vertex/fragment like this:

baseMaterialShader.modify(() => {
  let pos = varyingVec3()

  getObjectInputs((inputs) => {
    pos = inputs.position
    return inputs
  })

  getPixelInputs((inputs) => {
    // Do something with pos
  })
})

I propose that we take out the varyingVec3(), so it just looks like this:

baseMaterialShader.modify(() => {
  let pos

  getObjectInputs((inputs) => {
    pos = inputs.position
    return inputs
  })

  getPixelInputs((inputs) => {
    // Do something with pos
  })
})

We already detect when assigning from inside a hook to a variable in an outer scope, and when we do so, we can lazily create a variable as needed. Once we have that setup, this also lets us potentially support this:

baseMaterialShader.modify(() => {
  let pos

  getObjectInputs((inputs) => {
    pos = inputs.position
    return inputs
  })

  // Also in the vertex shader!
  getCameraInputs((inputs) => {
    inputs.color = mix([1, 0, 0, 1], [0, 0, 1, 1], length(inputs.position - pos))
    return inputs
  })
})

So instead of lazily creating a varying variable, we'd lazily create a generic global variable. This generic global does not yet know if it's a varying or a regular global. Only after we we run all the hooks, and we know where it's used, we would decide:

  • Output GLSL where it's a varying like we currently do if it's used in both a vertex shader hook and a fragment shader hook
  • Output a regular global variable if it's just used in vertex hooks or just used in fragment hooks

This would also require us to maybe track usage a little differently. Currently we do keep track of nodes that reference another node iirc, but we may want to check what shader a node is used in based on whether it gets referenced from the output of a hook and what stage that hook is for.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the p5.strands hooks around baseMaterialShader.modify, especially getObjectInputs and getPixelInputs, and trace how varyingVec3() references are currently tracked. Done means hook-to-hook values work without explicit varying declarations, while vertex/fragment use still produces varyings and same-stage use produces regular globals.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
computer-graphics
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.