From 83bb7e740eb0caeb99230cd998fb6b4356b09cd7 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Wed, 20 May 2026 14:35:37 -0400 Subject: [PATCH 1/2] Handle null tint in Renderer3D --- src/core/p5.Renderer3D.js | 7 +++++-- test/unit/visual/cases/webgl.js | 9 +++++++++ .../000.png | Bin 0 -> 7309 bytes .../metadata.json | 3 +++ 4 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 test/unit/visual/screenshots/WebGL/Opacity/noTint() before image() does not throw/000.png create mode 100644 test/unit/visual/screenshots/WebGL/Opacity/noTint() before image() does not throw/metadata.json diff --git a/src/core/p5.Renderer3D.js b/src/core/p5.Renderer3D.js index 6974561b4f..d83df0170d 100644 --- a/src/core/p5.Renderer3D.js +++ b/src/core/p5.Renderer3D.js @@ -137,7 +137,7 @@ export class Renderer3D extends Renderer { this.states._useShininess = 1; this.states._useMetalness = 0; - this.states.tint = new Color([1, 1, 1, 1]); + this.states.tint = null; this.states.constantAttenuation = 1; this.states.linearAttenuation = 0; @@ -1502,7 +1502,10 @@ export class Renderer3D extends Renderer { // works differently and is global p5 state. If the p5 state has // been cleared, we also need to clear the value in uSampler to match. fillShader.setUniform("uSampler", this.states._tex || empty); - fillShader.setUniform("uTint", this.states.tint._getRGBA([255, 255, 255, 255])); + fillShader.setUniform( + "uTint", + this.states.tint?._getRGBA([255, 255, 255, 255]) ?? [255, 255, 255, 255] + ); fillShader.setUniform("uHasSetAmbient", this.states._hasSetAmbient); fillShader.setUniform("uAmbientMatColor", this.states.curAmbientColor); diff --git a/test/unit/visual/cases/webgl.js b/test/unit/visual/cases/webgl.js index fd0cb09d0a..7519d4e2ea 100644 --- a/test/unit/visual/cases/webgl.js +++ b/test/unit/visual/cases/webgl.js @@ -645,6 +645,15 @@ visualSuite('WebGL', function() { p5.circle(0, 0, 50); screenshot(); }); + + visualTest('noTint() before image() does not throw', async (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const img = await p5.loadImage('/test/unit/assets/cat.jpg'); + p5.noTint(); + p5.imageMode(p5.CENTER); + p5.image(img, 0, 0, 50, 50); + screenshot(); + }); }); visualSuite('Hooks coordinate spaces', () => { diff --git a/test/unit/visual/screenshots/WebGL/Opacity/noTint() before image() does not throw/000.png b/test/unit/visual/screenshots/WebGL/Opacity/noTint() before image() does not throw/000.png new file mode 100644 index 0000000000000000000000000000000000000000..c92e8ba0a89d4e782a9055b7ac318c424e4bfc2b GIT binary patch literal 7309 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 Date: Wed, 20 May 2026 14:43:21 -0400 Subject: [PATCH 2/2] Update WebGL tests to allow null tint --- test/unit/webgl/p5.RendererGL.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/unit/webgl/p5.RendererGL.js b/test/unit/webgl/p5.RendererGL.js index 93582483b6..079b8000f6 100644 --- a/test/unit/webgl/p5.RendererGL.js +++ b/test/unit/webgl/p5.RendererGL.js @@ -1517,10 +1517,12 @@ suite('p5.RendererGL', function() { }); suite('tint() in WEBGL mode', function() { - test('default tint value is set and not null', function() { + test('default tint value', function() { myp5.createCanvas(100, 100, myp5.WEBGL); - assert.deepEqual(myp5._renderer.states.tint - ._getRGBA([255, 255, 255, 255]), [255, 255, 255, 255]); + assert.deepEqual( + myp5._renderer.states.tint?._getRGBA([255, 255, 255, 255]) ?? [255, 255, 255, 255], + [255, 255, 255, 255] + ); }); @@ -1581,7 +1583,7 @@ suite('p5.RendererGL', function() { }; }); }).then(function(_tint) { - assert.deepEqual(_tint._getRGBA([255, 255, 255, 255]), + assert.deepEqual(_tint?._getRGBA([255, 255, 255, 255]) ?? [255, 255, 255, 255], [255, 255, 255, 255]); }); });