Add shader examples for math functions#8802
Conversation
Add comprehensive shader examples for abs, ceil, exp, floor, lerp, log, map, max, min, pow, round, sqrt, and fract functions in p5.strands, demonstrating their usage in WebGL shaders with practical color effects.
nbogie
left a comment
There was a problem hiding this comment.
looks good though i didn't test the examples.
| * let t = millis() * 0.001; | ||
| * let value = 0.5 + 0.5 * sin(t); | ||
| * finalColor.begin(); | ||
| * finalColor.set(lerp([0, 0.8, 0.8, 1], [1, 0.5, 0.3, 1], value)); |
There was a problem hiding this comment.
As elsewhere, i think breaking this down is clearer
let mixFraction = ...
//define the two colours we'll mix between
//both as [r, g, b, a], all from 0.0 to 1.0
let color1 = [0, 0.8, 08, 1]
let color2 = [1, 0.5, 0.3, 1]
let mixedColor = lerp(color1, color2, mixFraction);
finalColor.set(mixedColor);This is also has quite a lot going on in order to demonstrate lerp: (millis and sin, and its normalization), but:
- I think it's ok, if we're assuming the expected reader already understands lerp from a 2d context.
- Otherwise a static form like `
//mix a color 25% cyan, 75% magenta
let mixedColor = lerp(cyan, magenta, 0.25);would be better suited.
However, your example is far more inspiring! I like it!
There was a problem hiding this comment.
perminder-17
left a comment
There was a problem hiding this comment.
On the website when I run your forked branch to check the actual changes, it looks something like this:
You can verify your changes by running the p5.js-website locally against your fork/branch of p5.js.
Here's the step
- Clone the website repository:
git clone https://github.com/processing/p5.js-website.git
cd p5.js-website
- Switch to the 2.0 branch (since you are working on the p5.js 2.x version):
git checkout 2.0
- Install dependencies:
npm install
Run the website against your p5.js branch using the custom:dev script.
npm run custom:dev https://github.com/SOUMITRO-SAHA/p5.js.git#docs-8777-strands-calc-examples
It would run your current changes.
Also, if you need to add new examples, you need to use the @example tag and then write your code instead of ```js . After the changes, you can verify by running the website locally with your changes. Thanks for your work so far :)
|
Thanks for the detailed steps and the screenshot, @perminder-17 ! I really appreciate you taking the time to verify this on the website and showing me how to set it up locally. I wasn't aware the website renders examples differently than how they appear in the web editor. I had been testing all the examples in the p5 web editor and using the ``js example syntax I saw in other parts of the codebase (like I'll:
Thanks for the guidance |
Convert all 13 inline shader examples from markdown code fence (```js example) to JSDoc @example tags so they render correctly on the p5.js website.
WhatsApp.Video.2026-05-20.at.20.08.44.mp4Hi, @perminder-17 , I am currently reviewing other examples that use the following format for examples: **```js example ** I am trying to understand the expected template and check whether this approach will work. From what I understood, we only need to move the example section before the I have also added a dummy video for testing. If this looks fine, then I will raise fixes for all the examples in PR 8001, 8002, and 8003 as well. |
8d1dc3e to
30f6c0e
Compare
|
Thanks @nbogie , @perminder-17 , and @davepagurek for all the feedback! I've tested all the changes locally on the I'll be applying a similar approach to the remaining PRs shortly. |
thanks for the update, I'll take a look soon. |
|
Hi @perminder-17 , just following up here. Any feedback on this PR, Let me know if anything else is needed. |
| * | ||
| * // In p5.strands, lerp() maps to the GLSL mix() function. | ||
| * // mix() blends teal (when value = 0) and coral (when value = 1). | ||
| * finalColor.set(mix(teal, coral, value)); |
There was a problem hiding this comment.
I think we should use lerp() here instead of mix() since it's in the example of lerp()
There was a problem hiding this comment.
I tried using lerp() initially, but it doesn't produce any visual changes on the p5.js website when rendered in a shader callback. Here's why:
In global mode, p5.js binds all prototype methods to window via bindGlobal() (main.js:99). So window.lerp gets the original scalar-only version. Later, when strands augments lerp to delegate to mix (strands_api.js:290), it uses augmentFn() which updates p5.prototype.lerp and p5.Graphics.prototype.lerp — but does NOT update window.lerp. The transpiled shader callback resolves lerp from the global scope, so it gets the original scalar-only version instead of the strands-aware one.
In contrast, mix() is a new function added by strands — there's no pre-existing window.mix binding, so it resolves correctly.
Do you think this is a bug? Since lerp() works in the playground, should I update the example to use lerp(), or keep using mix() as a workaround?
lerp-not-working.mp4
There was a problem hiding this comment.
You should use lerp, I think lerp is not defined at your library. Most likely you are using the older version of code. lerp is added recently in the library for strands. Can you please check what's getting on the console in your case? Is it says something like lerp() is not defined?
There was a problem hiding this comment.
+1 to Perminder's comment, lerp() is more consistently supported in recent release of 2.3. Thanks!
There was a problem hiding this comment.
Thanks @ksen0 and @perminder-17 for the context. I can confirm that after updating to p5.js version 2.3.0, lerp() is working properly in the shader callback. I've tested it and pushed the changes.
| * let value = log(1 + t) * 0.2; | ||
| * value = min(value, 1); |
There was a problem hiding this comment.
Can we do let value = min(log(1 + t * 2) * 0.4, 1); instead.
Also, 0.2 multiplier is too small, it will take a lot of time to reach yellow, so do you think you can use 0.4 instead?
| * // pow(t, 2) squares the time value: it starts slow then accelerates. | ||
| * // Multiply by 0.001 so it doesn't reach 1 too quickly. | ||
| * // min(..., 1) caps the value at 1. | ||
| * let value = min(pow(t, 2) * 0.001, 1); |
There was a problem hiding this comment.
| * let value = min(pow(t, 2) * 0.001, 1); | |
| * let value = pow(t, 2); |
perminder-17
left a comment
There was a problem hiding this comment.
Looks good! just some minor comments.
time-based animation examples for clarity and range.
Continuous ReleaseCDN linkPublished PackagesCommit hash: 8b12dcd Previous deploymentsThis is an automated message. |

Resolves #8777 (Calculation batch)
Changes:
Adds inline p5.strands examples to the reference documentation for 13 calculation functions in src/math/calculation.js:
abs()— mirror/fold effect using abs(sin(t))ceil()— stepped color bandsfloor()— posterized banding effectfract()— repeating gradient patternsqrt()— smooth easing curvepow()— gamma curve effectexp()— accelerating brightnesslog()— decelerating color transitionmin()— maximum brightness clampmax()— minimum brightness clampround()— quantized posterized colorslerp()— color blending (maps to GLSLmix)map()— remapped time to colorEach example uses
buildColorShader()withfinalColor.begin()/end()and includes a brief explanation that the function can be used in shaders with p5.strands.Screenshots of the change:
PR Checklist
npm run lintpasses