From 8c1a715b56e22c45b4a1cf5e158fc8aded45c76c Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Thu, 4 Dec 2025 13:31:28 -0500 Subject: [PATCH 1/2] Make sure camera methods on framebuffers work with push/pop --- src/webgl/p5.Camera.js | 5 +++ test/unit/visual/cases/webgl.js | 38 +++++++++++++++++- .../000.png | Bin 0 -> 1007 bytes .../metadata.json | 3 ++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 test/unit/visual/screenshots/WebGL/Camera/Camera settings on framebuffers reset after push%2Fpop/000.png create mode 100644 test/unit/visual/screenshots/WebGL/Camera/Camera settings on framebuffers reset after push%2Fpop/metadata.json diff --git a/src/webgl/p5.Camera.js b/src/webgl/p5.Camera.js index 9455d6a26e..019a7a1bc7 100644 --- a/src/webgl/p5.Camera.js +++ b/src/webgl/p5.Camera.js @@ -2945,15 +2945,18 @@ function camera(p5, fn){ p5.Camera = Camera; RendererGL.prototype.camera = function(...args) { + this.states.setValue('curCamera', this.states.curCamera.clone()); this.states.curCamera.camera(...args); }; RendererGL.prototype.perspective = function(...args) { + this.states.setValue('curCamera', this.states.curCamera.clone()); this.states.curCamera.perspective(...args); }; RendererGL.prototype.linePerspective = function(enable) { if (enable !== undefined) { + this.states.setValue('curCamera', this.states.curCamera.clone()); // Set the line perspective if enable is provided this.states.curCamera.useLinePerspective = enable; } else { @@ -2963,10 +2966,12 @@ function camera(p5, fn){ }; RendererGL.prototype.ortho = function(...args) { + this.states.setValue('curCamera', this.states.curCamera.clone()); this.states.curCamera.ortho(...args); }; RendererGL.prototype.frustum = function(...args) { + this.states.setValue('curCamera', this.states.curCamera.clone()); this.states.curCamera.frustum(...args); }; diff --git a/test/unit/visual/cases/webgl.js b/test/unit/visual/cases/webgl.js index ea732648fb..9dc8bb36a7 100644 --- a/test/unit/visual/cases/webgl.js +++ b/test/unit/visual/cases/webgl.js @@ -25,6 +25,42 @@ visualSuite('WebGL', function() { p5.box(20); screenshot(); }); + + visualTest('Camera settings on framebuffers reset after push/pop', function(p5, screenshot) { + p5.createCanvas(100, 100, p5.WEBGL); + p5.setAttributes({ antialias: true }); + const fbo = p5.createFramebuffer(); + + p5.background(220); + p5.imageMode(p5.CENTER); + + fbo.begin(); + p5.push(); + p5.ortho(); + p5.translate(0, -25); + for (let i = -1; i <= 1; i++) { + p5.push(); + p5.translate(i * 35, 0); + p5.box(25, 25, 150); + p5.pop(); + } + p5.pop(); + + + p5.push(); + p5.translate(0, 25); + for (let i = -1; i <= 1; i++) { + p5.push(); + p5.translate(i * 35, 0); + p5.box(25, 25, 150); + p5.pop(); + } + p5.pop(); + + fbo.end(); + p5.image(fbo, 0, 0); + screenshot(); + }); }); visualSuite('filter', function() { @@ -758,7 +794,7 @@ visualSuite('WebGL', function() { screenshot(); }); }); - + visualSuite('p5.strands', () => { visualTest('it recovers from p5.strands errors', (p5, screenshot) => { p5.createCanvas(50, 50, p5.WEBGL); diff --git a/test/unit/visual/screenshots/WebGL/Camera/Camera settings on framebuffers reset after push%2Fpop/000.png b/test/unit/visual/screenshots/WebGL/Camera/Camera settings on framebuffers reset after push%2Fpop/000.png new file mode 100644 index 0000000000000000000000000000000000000000..ccfdb9d58670f3fc53ceea44e3bae3c3ee8c919a GIT binary patch literal 1007 zcmeAS@N?(olHy`uVBq!ia0vp^DImFlsPnEzrqYz-sinL$bO4L+l=_kDF#*yfNqflB;zcDQY}tzgF$lepGQmTp-YG6kkpE`PY1|G8yx5ZdhBmx-)CnWH(OkT`MD&5I*V{h})K$1e>w%V>u9pNZRQ zqyD67uUh|%$1UxAS2|WaB;=K|!X!do!2E#?m>>Oou*hwOHLC5`ElKLqR5< z7~$6{6CSOxig?pNk}ilHKbW4>*r^|>+Uqy{bgR(qw~yN|ExXmo7FPRY?&rs;H<}OB zxha_cs`-qE@?Q9i$Z|2n9`*ET9-h77uiNv%i`L7mgb~qUCkmv45dSy`krTv!yYd=3k9yMu6{vqdV>IZ`qPkuCV>KZtdZg0~yALkDA6bCRpubWz$ITS|Is7?jajX zZ=%&6spwUG+tbVy3|`D$##|+MA?Mlmi%*$Y{wIB`TYm7&QYQIW@29_}EH^YhRbF{k zu9A`Yz0nbM!?$vqk4GB6`#O2vyW%g62EWUF(;iz&T}XG&F4=x?WA(Oa-~SYE-8(;d zZ`sciQpWMGYuQ3xKVaF8h{`n{C-UCG#JYD@<);T3K0RUe<(f$Ac literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/WebGL/Camera/Camera settings on framebuffers reset after push%2Fpop/metadata.json b/test/unit/visual/screenshots/WebGL/Camera/Camera settings on framebuffers reset after push%2Fpop/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/WebGL/Camera/Camera settings on framebuffers reset after push%2Fpop/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file From cdec32f75184b4092bd39d241f1804f7ca2174c1 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Thu, 4 Dec 2025 13:47:19 -0500 Subject: [PATCH 2/2] Fix clone() on framebuffer cameras --- src/webgl/p5.Camera.js | 2 ++ src/webgl/p5.Framebuffer.js | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/webgl/p5.Camera.js b/src/webgl/p5.Camera.js index 019a7a1bc7..8227c8769c 100644 --- a/src/webgl/p5.Camera.js +++ b/src/webgl/p5.Camera.js @@ -1844,6 +1844,8 @@ class Camera { _cam.projMatrix = this.projMatrix.copy(); _cam.yScale = this.yScale; + _cam.cameraType = this.cameraType; + return _cam; } diff --git a/src/webgl/p5.Framebuffer.js b/src/webgl/p5.Framebuffer.js index a3d6875068..032c4812db 100644 --- a/src/webgl/p5.Framebuffer.js +++ b/src/webgl/p5.Framebuffer.js @@ -31,6 +31,12 @@ class FramebufferCamera extends Camera { this.defaultCameraFOV = 2 * Math.atan(this.fbo.height / 2 / this.defaultEyeZ); } + + copy() { + const _cam = super.copy(); + _cam.fbo = this.fbo; + return _cam; + } } class FramebufferTexture {