@@ -30,7 +30,11 @@ function strands(p5, fn) {
3030 //////////////////////////////////////////////
3131 // Global Runtime
3232 //////////////////////////////////////////////
33- function initStrandsContext ( ctx , backend , { active = false , renderer = null , baseShader = null } = { } ) {
33+ function initStrandsContext (
34+ ctx ,
35+ backend ,
36+ { active = false , renderer = null , baseShader = null } = { } ,
37+ ) {
3438 ctx . dag = createDirectedAcyclicGraph ( ) ;
3539 ctx . cfg = createControlFlowGraph ( ) ;
3640 ctx . uniforms = [ ] ;
@@ -78,11 +82,8 @@ function strands(p5, fn) {
7882
7983 const prev = { } ;
8084 for ( const key of Object . getOwnPropertyNames ( fn ) ) {
81- const descriptor = Object . getOwnPropertyDescriptor (
82- fn ,
83- key
84- ) ;
85- if ( descriptor && ! descriptor . get && typeof fn [ key ] === 'function' ) {
85+ const descriptor = Object . getOwnPropertyDescriptor ( fn , key ) ;
86+ if ( descriptor && ! descriptor . get && typeof fn [ key ] === "function" ) {
8687 prev [ key ] = window [ key ] ;
8788 window [ key ] = fn [ key ] . bind ( pInst ) ;
8889 }
@@ -104,7 +105,10 @@ function strands(p5, fn) {
104105
105106 p5 . Shader . prototype . modify = function ( shaderModifier , scope = { } ) {
106107 try {
107- if ( shaderModifier instanceof Function || typeof shaderModifier === 'string' ) {
108+ if (
109+ shaderModifier instanceof Function ||
110+ typeof shaderModifier === "string"
111+ ) {
108112 // Reset the context object every time modify is called;
109113 // const backend = glslBackend;
110114 initStrandsContext ( strandsContext , this . _renderer . strandsBackend , {
@@ -121,9 +125,10 @@ function strands(p5, fn) {
121125 if ( options . parser ) {
122126 // #7955 Wrap function declaration code in brackets so anonymous functions are not top level statements, which causes an error in acorn when parsing
123127 // https://github.com/acornjs/acorn/issues/1385
124- const sourceString = typeof shaderModifier === 'string'
125- ? `(${ shaderModifier } )`
126- : `(${ shaderModifier . toString ( ) } )` ;
128+ const sourceString =
129+ typeof shaderModifier === "string"
130+ ? `(${ shaderModifier } )`
131+ : `(${ shaderModifier . toString ( ) } )` ;
127132 strandsCallback = transpileStrandsToJS (
128133 p5 ,
129134 sourceString ,
@@ -267,6 +272,100 @@ if (typeof p5 !== "undefined") {
267272 * }
268273 */
269274
275+ /**
276+ * @method smoothstep
277+ * @description
278+ * A shader function that performs smooth Hermite interpolation between `0.0`
279+ * and `1.0`.
280+ *
281+ * This function is equivalent to the GLSL built-in
282+ * `smoothstep(edge0, edge1, x)` and is available inside p5.strands shader
283+ * callbacks. It is commonly used to create soft transitions, smooth edges,
284+ * fades, and anti-aliased effects.
285+ *
286+ * Smoothstep is useful when a threshold or cutoff is needed, but with a
287+ * gradual transition instead of a hard edge.
288+ *
289+ * - Returns `0.0` when `x` is less than or equal to `edge0`
290+ * - Returns `1.0` when `x` is greater than or equal to `edge1`
291+ * - Smoothly interpolates between `0.0` and `1.0` when `x` is between them
292+ *
293+ * @param {Number } edge0
294+ * Lower edge of the transition
295+ * @param {Number } edge1
296+ * Upper edge of the transition
297+ * @param {Number } x
298+ * Input value to interpolate
299+ *
300+ * @returns {Number }
301+ * A value between `0.0` and `1.0`
302+ *
303+ * @example
304+ * <div modernizr="webgl">
305+ * <code>
306+ * // Example 1: A soft vertical fade using smoothstep (no uniforms)
307+ *
308+ * let fadeShader;
309+ *
310+ * function fadeCallback() {
311+ * getColor((inputs) => {
312+ * // x goes from 0 → 1 across the canvas
313+ * let x = inputs.texCoord.x;
314+ *
315+ * // smoothstep creates a soft transition instead of a hard edge
316+ * let t = smoothstep(0.25, 0.35, x);
317+ *
318+ * // Use t directly as brightness
319+ * return [t, t, t, 1];
320+ * });
321+ * }
322+ *
323+ * function setup() {
324+ * createCanvas(300, 200, WEBGL);
325+ * fadeShader = baseFilterShader().modify(fadeCallback);
326+ * }
327+ *
328+ * function draw() {
329+ * background(0);
330+ * filter(fadeShader);
331+ * }
332+ * </code>
333+ * </div>
334+ *
335+ * @example
336+ * <div modernizr="webgl">
337+ * <code>
338+ * // Example 2: Animate the smooth transition using a uniform
339+ *
340+ * let animatedShader;
341+ *
342+ * function animatedFadeCallback() {
343+ * const time = uniformFloat(() => millis() * 0.001);
344+ *
345+ * getColor((inputs) => {
346+ * let x = inputs.texCoord.x;
347+ *
348+ * // Move the smoothstep band back and forth over time
349+ * let center = 0.5 + 0.25 * sin(time);
350+ * let t = smoothstep(center - 0.05, center + 0.05, x);
351+ *
352+ * return [t, t, t, 1];
353+ * });
354+ * }
355+ *
356+ * function setup() {
357+ * createCanvas(300, 200, WEBGL);
358+ * animatedShader = baseFilterShader().modify(animatedFadeCallback);
359+ * }
360+ *
361+ * function draw() {
362+ * background(0);
363+ * filter(animatedShader);
364+ * }
365+ * </code>
366+ * </div>
367+ */
368+
270369/**
271370 * @method beforeVertex
272371 * @private
0 commit comments