Skip to content

Commit d3bb21c

Browse files
authored
Merge pull request #8753 from Nixxx19/nityam/strands-map-8750
support map() inside p5.strands shaders
2 parents 107f3c0 + 37cc939 commit d3bb21c

2 files changed

Lines changed: 139 additions & 0 deletions

File tree

src/strands/strands_api.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,23 @@ export function initGlobalStrandsAPI(p5, fn, strandsContext) {
294294
}
295295
});
296296

297+
const originalMap = fn.map;
298+
augmentFn(fn, p5, 'map', function (...args) {
299+
if (!strandsContext.active) {
300+
return originalMap.apply(this, args);
301+
}
302+
const [n, start1, stop1, start2, stop2, withinBounds] = args;
303+
const nNode = p5.strandsNode(n);
304+
const start1Node = p5.strandsNode(start1);
305+
const stop1Node = p5.strandsNode(stop1);
306+
const t = nNode.sub(start1Node).div(stop1Node.sub(start1Node));
307+
const result = this.mix(start2, stop2, t);
308+
if (withinBounds) {
309+
return this.clamp(result, this.min(start2, stop2), this.max(start2, stop2));
310+
}
311+
return result;
312+
});
313+
297314
augmentFn(fn, p5, 'getTexture', function (...rawArgs) {
298315
if (strandsContext.active) {
299316
const { id, dimension } = strandsContext.backend.createGetTextureCall(strandsContext, rawArgs);

test/unit/webgl/p5.Shader.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,128 @@ test('returns numbers for builtin globals outside hooks and a strandNode when ca
495495
});
496496

497497

498+
test('map() works inside a strands modify callback', () => {
499+
myp5.createCanvas(50, 50, myp5.WEBGL);
500+
const testShader = myp5.baseMaterialShader().modify(() => {
501+
myp5.getPixelInputs(inputs => {
502+
const v = myp5.map(0.25, 0, 1, 0, 1);
503+
inputs.color = [v, v, v, 1.0];
504+
return inputs;
505+
});
506+
}, { myp5 });
507+
508+
myp5.noStroke();
509+
myp5.shader(testShader);
510+
myp5.plane(myp5.width, myp5.height);
511+
512+
const pixelColor = myp5.get(25, 25);
513+
assert.approximately(pixelColor[0], 64, 5);
514+
assert.approximately(pixelColor[1], 64, 5);
515+
assert.approximately(pixelColor[2], 64, 5);
516+
});
517+
518+
test('map() with withinBounds clamps the result inside strands', () => {
519+
myp5.createCanvas(50, 50, myp5.WEBGL);
520+
const testShader = myp5.baseMaterialShader().modify(() => {
521+
myp5.getPixelInputs(inputs => {
522+
const v = myp5.map(2.0, 0, 1, 0, 1, true);
523+
inputs.color = [v, v, v, 1.0];
524+
return inputs;
525+
});
526+
}, { myp5 });
527+
528+
myp5.noStroke();
529+
myp5.shader(testShader);
530+
myp5.plane(myp5.width, myp5.height);
531+
532+
const pixelColor = myp5.get(25, 25);
533+
assert.approximately(pixelColor[0], 255, 5);
534+
assert.approximately(pixelColor[1], 255, 5);
535+
assert.approximately(pixelColor[2], 255, 5);
536+
});
537+
538+
test('map() shrinks a wider input range into a narrower output range', () => {
539+
myp5.createCanvas(50, 50, myp5.WEBGL);
540+
const testShader = myp5.baseMaterialShader().modify(() => {
541+
myp5.getPixelInputs(inputs => {
542+
const v = myp5.map(5, 0, 10, 0, 1);
543+
inputs.color = [v, v, v, 1.0];
544+
return inputs;
545+
});
546+
}, { myp5 });
547+
548+
myp5.noStroke();
549+
myp5.shader(testShader);
550+
myp5.plane(myp5.width, myp5.height);
551+
552+
const pixelColor = myp5.get(25, 25);
553+
assert.approximately(pixelColor[0], 128, 5);
554+
assert.approximately(pixelColor[1], 128, 5);
555+
assert.approximately(pixelColor[2], 128, 5);
556+
});
557+
558+
test('map() handles offset output ranges correctly', () => {
559+
myp5.createCanvas(50, 50, myp5.WEBGL);
560+
const testShader = myp5.baseMaterialShader().modify(() => {
561+
myp5.getPixelInputs(inputs => {
562+
const v = myp5.map(0.5, 0, 1, 0.2, 0.8);
563+
inputs.color = [v, v, v, 1.0];
564+
return inputs;
565+
});
566+
}, { myp5 });
567+
568+
myp5.noStroke();
569+
myp5.shader(testShader);
570+
myp5.plane(myp5.width, myp5.height);
571+
572+
const pixelColor = myp5.get(25, 25);
573+
assert.approximately(pixelColor[0], 128, 5);
574+
assert.approximately(pixelColor[1], 128, 5);
575+
assert.approximately(pixelColor[2], 128, 5);
576+
});
577+
578+
test('map() handles a negative input range', () => {
579+
myp5.createCanvas(50, 50, myp5.WEBGL);
580+
const testShader = myp5.baseMaterialShader().modify(() => {
581+
myp5.getPixelInputs(inputs => {
582+
const v = myp5.map(0, -1, 1, 0, 1);
583+
inputs.color = [v, v, v, 1.0];
584+
return inputs;
585+
});
586+
}, { myp5 });
587+
588+
myp5.noStroke();
589+
myp5.shader(testShader);
590+
myp5.plane(myp5.width, myp5.height);
591+
592+
const pixelColor = myp5.get(25, 25);
593+
assert.approximately(pixelColor[0], 128, 5);
594+
assert.approximately(pixelColor[1], 128, 5);
595+
assert.approximately(pixelColor[2], 128, 5);
596+
});
597+
598+
test('map() remaps texCoord.x into a horizontal gradient', () => {
599+
myp5.createCanvas(50, 50, myp5.WEBGL);
600+
const testShader = myp5.baseMaterialShader().modify(() => {
601+
myp5.getPixelInputs(inputs => {
602+
const v = myp5.map(inputs.texCoord.x, 0, 1, 0.2, 0.8);
603+
inputs.color = [v, v, v, 1.0];
604+
return inputs;
605+
});
606+
}, { myp5 });
607+
608+
myp5.noStroke();
609+
myp5.shader(testShader);
610+
myp5.plane(myp5.width, myp5.height);
611+
612+
const left = myp5.get(2, 25);
613+
const middle = myp5.get(25, 25);
614+
const right = myp5.get(47, 25);
615+
assert.approximately(left[0], 51, 10);
616+
assert.approximately(middle[0], 128, 10);
617+
assert.approximately(right[0], 204, 10);
618+
});
619+
498620
test('handle custom uniform names with automatic values', () => {
499621
myp5.createCanvas(50, 50, myp5.WEBGL);
500622
const testShader = myp5.baseMaterialShader().modify(() => {

0 commit comments

Comments
 (0)