Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 106 additions & 10 deletions src/strands/p5.strands.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ function strands(p5, fn) {
//////////////////////////////////////////////
// Global Runtime
//////////////////////////////////////////////
function initStrandsContext(ctx, backend, { active = false, renderer = null, baseShader = null } = {}) {
function initStrandsContext(
ctx,
backend,
{ active = false, renderer = null, baseShader = null } = {},
) {
ctx.dag = createDirectedAcyclicGraph();
ctx.cfg = createControlFlowGraph();
ctx.uniforms = [];
Expand Down Expand Up @@ -78,11 +82,8 @@ function strands(p5, fn) {

const prev = {};
for (const key of Object.getOwnPropertyNames(fn)) {
const descriptor = Object.getOwnPropertyDescriptor(
fn,
key
);
if (descriptor && !descriptor.get && typeof fn[key] === 'function') {
const descriptor = Object.getOwnPropertyDescriptor(fn, key);
if (descriptor && !descriptor.get && typeof fn[key] === "function") {
prev[key] = window[key];
window[key] = fn[key].bind(pInst);
}
Expand All @@ -104,7 +105,10 @@ function strands(p5, fn) {

p5.Shader.prototype.modify = function (shaderModifier, scope = {}) {
try {
if (shaderModifier instanceof Function || typeof shaderModifier === 'string') {
if (
shaderModifier instanceof Function ||
typeof shaderModifier === "string"
) {
// Reset the context object every time modify is called;
// const backend = glslBackend;
initStrandsContext(strandsContext, this._renderer.strandsBackend, {
Expand All @@ -121,9 +125,10 @@ function strands(p5, fn) {
if (options.parser) {
// #7955 Wrap function declaration code in brackets so anonymous functions are not top level statements, which causes an error in acorn when parsing
// https://github.com/acornjs/acorn/issues/1385
const sourceString = typeof shaderModifier === 'string'
? `(${shaderModifier})`
: `(${shaderModifier.toString()})`;
const sourceString =
typeof shaderModifier === "string"
? `(${shaderModifier})`
: `(${shaderModifier.toString()})`;
strandsCallback = transpileStrandsToJS(
p5,
sourceString,
Expand Down Expand Up @@ -275,6 +280,97 @@ if (typeof p5 !== "undefined") {
* </div>
*/

/**
* @method smoothstep
* @description
* A shader function that performs smooth Hermite interpolation between `0.0`
* and `1.0`.
*
* This function is equivalent to the GLSL built-in
* `smoothstep(edge0, edge1, x)` and is available inside p5.strands shader
* callbacks. It is commonly used to create soft transitions, smooth edges,
* fades, and anti-aliased effects.
*
* - Returns `0.0` when `x` is less than or equal to `edge0`
* - Returns `1.0` when `x` is greater than or equal to `edge1`
* - Smoothly interpolates between `0.0` and `1.0` when `x` is between them
*
* @param {Number} edge0
* Lower edge of the transition
* @param {Number} edge1
* Upper edge of the transition
* @param {Number} x
* Input value to interpolate
*
* @returns {Number}
* A value between `0.0` and `1.0`
*
* @example
* <div modernizr="webgl">
* <code>
* // Example 1: A soft vertical fade using smoothstep (no uniforms)
*
* let fadeShader;
*
* function fadeCallback() {
* getColor((inputs) => {
* // x goes from 0 → 1 across the canvas
* let x = inputs.texCoord.x;
*
* // smoothstep creates a soft transition instead of a hard edge
* let t = smoothstep(0.45, 0.55, x);
*
* // Use t directly as brightness
* return [t, t, t, 1];
* });
* }
*
* function setup() {
* createCanvas(300, 200, WEBGL);
* fadeShader = baseFilterShader().modify(fadeCallback);
* }
*
* function draw() {
* background(0);
* filter(fadeShader);
* }
* </code>
* </div>
*
* @example
* <div modernizr="webgl">
* <code>
* // Example 2: Animate the smooth transition using a uniform
*
* let animatedShader;
*
* function animatedFadeCallback() {
* const time = uniformFloat(() => millis() * 0.001);
*
* getColor((inputs) => {
* let x = inputs.texCoord.x;
*
* // Move the smoothstep band back and forth over time
* let center = 0.5 + 0.25 * sin(time);
* let t = smoothstep(center - 0.05, center + 0.05, x);
*
* return [t, t, t, 1];
* });
* }
*
* function setup() {
* createCanvas(300, 200, WEBGL);
* animatedShader = baseFilterShader().modify(animatedFadeCallback);
* }
*
* function draw() {
* background(0);
* filter(animatedShader);
* }
* </code>
* </div>
*/

/**
* @method beforeVertex
* @private
Expand Down