Skip to content

Fix build*Shader methods in instance mode by forwarding optional scope#8523

Merged
davepagurek merged 3 commits intoprocessing:dev-2.0from
aashu2006:fix-build-shader-instance-mode
Feb 18, 2026
Merged

Fix build*Shader methods in instance mode by forwarding optional scope#8523
davepagurek merged 3 commits intoprocessing:dev-2.0from
aashu2006:fix-build-shader-instance-mode

Conversation

@aashu2006
Copy link

@aashu2006 aashu2006 commented Feb 11, 2026

Resolves #8520

Changes

The five build*Shader methods in src/webgl/material.js were calling .modify(callback) without forwarding the optional scope parameter.

In instance mode, users pass { p5 } or { sketch } as scope so the callback receives the correct instance. Since this argument was not forwarded, the callback didn’t receive the expected context.

This PR updates these methods to accept an optional scope parameter and pass it to .modify(callback, scope)

No changes are made to .modify() itself, and existing code without scope continues to work.

I have also added a unit test under test/unit/webgl/p5.Shader.js (inside the existing p5.strands suite) to verify that buildMaterialShader correctly forwards the optional scope to .modify(). JSDoc comments were updated to document the optional scope parameter.

// Before
fn.buildFilterShader = function (callback) {
  return this.baseFilterShader().modify(callback);
};

// After
fn.buildFilterShader = function (callback, scope) {
  return this.baseFilterShader().modify(callback, scope);
};

PR Checklist

@davepagurek
Copy link
Contributor

Thanks for taking this on! It's looking good so far, but can we add a unit test for one of these methods to make sure it continues to work going forward? Also, can we add the optional context parameter to the doc comments, mirroring what is found in the p5.Shader.modify doc comments?

@aashu2006
Copy link
Author

Hii @davepagurek I have added the unit test for scope forwarding and updated the JSDoc comments as suggested. All tests pass locally. Thanks ❤️

@@ -0,0 +1,25 @@
import p5 from '../../../src/app.js';

suite('p5.Shader', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! The test looks good, is there a reason why this is in its own file as opposed to the existing p5.Shader unit tests file? It might be better in there.

Also, generally the tests in that file don't create a new instance, they reuse a myp5 instance. To have less moving parts, they also omit a setup function, they just create a canvas, initialize whatever they need to, and then make their assertions. This means you wouldn't need a done function.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that's right! I will move the test into p5.Shader.js and update it to reuse myp5 like the other tests, without creating a new instance or using done.

let receivedSketch = null;

sketch.buildMaterialShader(function({ sketch: s }) {
receivedSketch = s;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5.strands shaders don't have the ability to assign to variables outside of their functions -- since we transpile them, they lose all external scope, which is the reason why we have to manually pass scope in.

Rather than doing something like this in the test, we can maybe just use scope the way we use it in the .modify calls in the other tests, e.g. this call, before your changes, wouldn't work with buildMaterialShader:

const testShader = myp5.baseMaterialShader().modify(() => {
const x = myp5.uniformFloat(() => 1.0); // true condition
myp5.getPixelInputs(inputs => {
let color = myp5.float(0.5); // initial gray
if (x > 0.5) {
color = myp5.float(1.0); // set to white in if branch
}
inputs.color = [color, color, color, 1.0];
return inputs;
});
}, { myp5 });

We can just wrap the creation of the shader in an expect(() => { /* ... */ }).not.toThrow() call maybe?

Copy link
Author

@aashu2006 aashu2006 Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining, I will update the test to follow the existing .modify() pattern and wrap the shader creation in an expect(() => {}).not.toThrowError() call instead of assigning to external variables.

@aashu2006 aashu2006 force-pushed the fix-build-shader-instance-mode branch from 478e147 to bec8391 Compare February 18, 2026 08:46
@aashu2006
Copy link
Author

Hi @davepagurek . I have moved the scope test into p5.Shader.js under the existing p5.strands suite and aligned it with the surrounding test style. All tests have passed locally. Thanks 🙂

Copy link
Contributor

@davepagurek davepagurek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! thanks again!

@davepagurek davepagurek merged commit 9e0b550 into processing:dev-2.0 Feb 18, 2026
2 checks passed
@aashu2006
Copy link
Author

Awesome! thanks again!

Thanks a lot for the review and guidance, I really appreciate the time you took to explain the test structure & strands behavior. Learned a lot from this one 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants