Skip to content

Commit 95a5df2

Browse files
authored
Merge pull request #8459 from jjnawaaz/docs-smoothstep-strands
docs(p5.strands): document smoothstep
2 parents aaff6a7 + 6006d47 commit 95a5df2

1 file changed

Lines changed: 109 additions & 10 deletions

File tree

src/strands/p5.strands.js

Lines changed: 109 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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,
@@ -275,6 +280,100 @@ if (typeof p5 !== "undefined") {
275280
* </div>
276281
*/
277282

283+
/**
284+
* @method smoothstep
285+
* @description
286+
* A shader function that performs smooth Hermite interpolation between `0.0`
287+
* and `1.0`.
288+
*
289+
* This function is equivalent to the GLSL built-in
290+
* `smoothstep(edge0, edge1, x)` and is available inside p5.strands shader
291+
* callbacks. It is commonly used to create soft transitions, smooth edges,
292+
* fades, and anti-aliased effects.
293+
*
294+
* Smoothstep is useful when a threshold or cutoff is needed, but with a
295+
* gradual transition instead of a hard edge.
296+
*
297+
* - Returns `0.0` when `x` is less than or equal to `edge0`
298+
* - Returns `1.0` when `x` is greater than or equal to `edge1`
299+
* - Smoothly interpolates between `0.0` and `1.0` when `x` is between them
300+
*
301+
* @param {Number} edge0
302+
* Lower edge of the transition
303+
* @param {Number} edge1
304+
* Upper edge of the transition
305+
* @param {Number} x
306+
* Input value to interpolate
307+
*
308+
* @returns {Number}
309+
* A value between `0.0` and `1.0`
310+
*
311+
* @example
312+
* <div modernizr="webgl">
313+
* <code>
314+
* // Example 1: A soft vertical fade using smoothstep (no uniforms)
315+
*
316+
* let fadeShader;
317+
*
318+
* function fadeCallback() {
319+
* getColor((inputs) => {
320+
* // x goes from 0 → 1 across the canvas
321+
* let x = inputs.texCoord.x;
322+
*
323+
* // smoothstep creates a soft transition instead of a hard edge
324+
* let t = smoothstep(0.25, 0.35, x);
325+
*
326+
* // Use t directly as brightness
327+
* return [t, t, t, 1];
328+
* });
329+
* }
330+
*
331+
* function setup() {
332+
* createCanvas(300, 200, WEBGL);
333+
* fadeShader = baseFilterShader().modify(fadeCallback);
334+
* }
335+
*
336+
* function draw() {
337+
* background(0);
338+
* filter(fadeShader);
339+
* }
340+
* </code>
341+
* </div>
342+
*
343+
* @example
344+
* <div modernizr="webgl">
345+
* <code>
346+
* // Example 2: Animate the smooth transition using a uniform
347+
*
348+
* let animatedShader;
349+
*
350+
* function animatedFadeCallback() {
351+
* const time = uniformFloat(() => millis() * 0.001);
352+
*
353+
* getColor((inputs) => {
354+
* let x = inputs.texCoord.x;
355+
*
356+
* // Move the smoothstep band back and forth over time
357+
* let center = 0.5 + 0.25 * sin(time);
358+
* let t = smoothstep(center - 0.05, center + 0.05, x);
359+
*
360+
* return [t, t, t, 1];
361+
* });
362+
* }
363+
*
364+
* function setup() {
365+
* createCanvas(300, 200, WEBGL);
366+
* animatedShader = baseFilterShader().modify(animatedFadeCallback);
367+
* }
368+
*
369+
* function draw() {
370+
* background(0);
371+
* filter(animatedShader);
372+
* }
373+
* </code>
374+
* </div>
375+
*/
376+
278377
/**
279378
* @method beforeVertex
280379
* @private

0 commit comments

Comments
 (0)