From daa10e6556e2df960c0239b739052048afead646 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Mon, 10 Nov 2025 16:31:42 -0500 Subject: [PATCH] Fix usage of int() typecast in p5.strands --- src/strands/strands_api.js | 14 ++++- src/strands/strands_node.js | 18 +++++-- src/webgl/p5.Shader.js | 4 +- test/unit/visual/cases/webgl.js | 50 ++++++++++++++++++ .../can draw in a grid with floor()/000.png | Bin 0 -> 796 bytes .../metadata.json | 3 ++ .../can draw in a grid with int()/000.png | Bin 0 -> 796 bytes .../metadata.json | 3 ++ 8 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 test/unit/visual/screenshots/WebGL/instanced randering/can draw in a grid with floor()/000.png create mode 100644 test/unit/visual/screenshots/WebGL/instanced randering/can draw in a grid with floor()/metadata.json create mode 100644 test/unit/visual/screenshots/WebGL/instanced randering/can draw in a grid with int()/000.png create mode 100644 test/unit/visual/screenshots/WebGL/instanced randering/can draw in a grid with int()/metadata.json diff --git a/src/strands/strands_api.js b/src/strands/strands_api.js index fb88413749..3ee5f15666 100644 --- a/src/strands/strands_api.js +++ b/src/strands/strands_api.js @@ -205,8 +205,18 @@ export function initGlobalStrandsAPI(p5, fn, strandsContext) { const originalp5Fn = fn[typeInfo.fnName]; fn[typeInfo.fnName] = function(...args) { if (strandsContext.active) { - const { id, dimension } = build.primitiveConstructorNode(strandsContext, typeInfo, args); - return createStrandsNode(id, dimension, strandsContext); + if (args.length === 1 && args[0].dimension && args[0].dimension === typeInfo.dimension) { + const { id, dimension } = build.functionCallNode(strandsContext, typeInfo.fnName, args, { + overloads: [{ + params: [args[0].typeInfo()], + returnType: typeInfo, + }] + }); + return createStrandsNode(id, dimension, strandsContext); + } else { + const { id, dimension } = build.primitiveConstructorNode(strandsContext, typeInfo, args); + return createStrandsNode(id, dimension, strandsContext); + } } else if (originalp5Fn) { return originalp5Fn.apply(this, args); } else { diff --git a/src/strands/strands_node.js b/src/strands/strands_node.js index 0901355aff..bfa58d0c89 100644 --- a/src/strands/strands_node.js +++ b/src/strands/strands_node.js @@ -13,6 +13,8 @@ export class StrandsNode { const nodeData = getNodeDataFromID(dag, this.id); if (nodeData && nodeData.identifier) { this._originalIdentifier = nodeData.identifier; + } + if (nodeData) { this._originalBaseType = nodeData.baseType; this._originalDimension = nodeData.dimension; } @@ -20,6 +22,12 @@ export class StrandsNode { copy() { return createStrandsNode(this.id, this.dimension, this.strandsContext); } + typeInfo() { + return { + baseType: this._originalBaseType || BaseType.FLOAT, + dimension: this.dimension + }; + } bridge(value) { const { dag, cfg } = this.strandsContext; const orig = getNodeDataFromID(dag, this.id); @@ -30,8 +38,8 @@ export class StrandsNode { newValueID = value.id; } else { const newVal = primitiveConstructorNode( - this.strandsContext, - { baseType, dimension: this.dimension }, + this.strandsContext, + { baseType, dimension: this.dimension }, value ); newValueID = newVal.id; @@ -85,8 +93,8 @@ export class StrandsNode { newValueID = value.id; } else { const newVal = primitiveConstructorNode( - this.strandsContext, - { baseType, dimension: this.dimension }, + this.strandsContext, + { baseType, dimension: this.dimension }, value ); newValueID = newVal.id; @@ -159,4 +167,4 @@ export function createStrandsNode(id, dimension, strandsContext, onRebind) { new StrandsNode(id, dimension, strandsContext), swizzleTrap(id, dimension, strandsContext, onRebind) ); -} \ No newline at end of file +} diff --git a/src/webgl/p5.Shader.js b/src/webgl/p5.Shader.js index cecd7ae992..b0dadd2466 100644 --- a/src/webgl/p5.Shader.js +++ b/src/webgl/p5.Shader.js @@ -533,7 +533,7 @@ class Shader { // if our vertex shader failed compilation? if (!gl.getShaderParameter(this._vertShader, gl.COMPILE_STATUS)) { const glError = gl.getShaderInfoLog(this._vertShader); - if (typeof IS_MINIFIED !== 'undefined') { + if (typeof IS_MINIFIED !== 'undefined' || typeof p5 === 'undefined') { console.error(glError); } else { p5._friendlyError( @@ -551,7 +551,7 @@ class Shader { // if our frag shader failed compilation? if (!gl.getShaderParameter(this._fragShader, gl.COMPILE_STATUS)) { const glError = gl.getShaderInfoLog(this._fragShader); - if (typeof IS_MINIFIED !== 'undefined') { + if (typeof IS_MINIFIED !== 'undefined' || typeof p5 === 'undefined') { console.error(glError); } else { p5._friendlyError( diff --git a/test/unit/visual/cases/webgl.js b/test/unit/visual/cases/webgl.js index 66a04198a5..12f5def132 100644 --- a/test/unit/visual/cases/webgl.js +++ b/test/unit/visual/cases/webgl.js @@ -708,4 +708,54 @@ visualSuite('WebGL', function() { screenshot(); }); }); + + visualSuite('instanced randering', async () => { + visualTest('can draw in a grid with floor()', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const shader = p5.baseMaterialShader().modify(() => { + p5.getWorldInputs((inputs) => { + const id = p5.instanceID(); + const gridSize = 5; + const row = p5.floor(id / gridSize); + const col = id - row * gridSize; + const blockInnerSize = 10; + const x = (col - gridSize / 2.0) * blockInnerSize + blockInnerSize/2; + const y = (gridSize / 2.0 - row) * blockInnerSize - blockInnerSize/2; + inputs.position += [x, y, 0]; + return inputs; + }); + }, { p5 }); + p5.shader(shader); + const obj = p5.buildGeometry(() => p5.circle(0, 0, 6)) + p5.noStroke(); + p5.fill(0); + p5.shader(shader); + p5.model(obj, 25); + screenshot(); + }); + + visualTest('can draw in a grid with int()', (p5, screenshot) => { + p5.createCanvas(50, 50, p5.WEBGL); + const shader = p5.baseMaterialShader().modify(() => { + p5.getWorldInputs((inputs) => { + const id = p5.instanceID(); + const gridSize = 5; + const row = p5.int(id / gridSize); + const col = id - row * gridSize; + const blockInnerSize = 10; + const x = (col - gridSize / 2.0) * blockInnerSize + blockInnerSize/2; + const y = (gridSize / 2.0 - row) * blockInnerSize - blockInnerSize/2; + inputs.position += [x, y, 0]; + return inputs; + }); + }, { p5 }); + p5.shader(shader); + const obj = p5.buildGeometry(() => p5.circle(0, 0, 6)) + p5.noStroke(); + p5.fill(0); + p5.shader(shader); + p5.model(obj, 25); + screenshot(); + }); + }); }); diff --git a/test/unit/visual/screenshots/WebGL/instanced randering/can draw in a grid with floor()/000.png b/test/unit/visual/screenshots/WebGL/instanced randering/can draw in a grid with floor()/000.png new file mode 100644 index 0000000000000000000000000000000000000000..03b17b94e0cae682c3e7be5f235eb144afe02ab6 GIT binary patch literal 796 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2o;fFkSR?aSW+od~@~Us@nzvEs5Lp z?|nNNU0-dJxO;_oEAw$KzR2un^HnpF8~4fQf2zFgST|4q#rM!Jn$zQNuKo2(dgD&{ z+}kGC0z7@fp4D8qq51z;(k2I~?(8*N`5Z~gl|xpqQ) z_uKr#zZA|z-?!*J`_mxOqW5U}(UgxSV)I2OAH5t=6Xql4pZxTmu~!6%RE{3diycG-%$pU45+sJwCh-qP@MyGNACaMC+#}8)BHB@zHYY2uYGJ{ z)_yqUA*ypeMjA%i^iF->%)qpL*`kf1C%4XopFeANZkqkl_!TB*xA=U@V&tWEzsWwB!e|neV?6?CC}G2dG#cq_gAq`ei>-8O>3r{>-s7K zAekImJfX?jZl2@2Z`Ynl7rvV}yLOLiz1RML%$zNmIuw&@ITt~wfFK38NSJ_uvmb28xlQX`}mnS?#${s7N&Z6@rzJ? zwabe$azc%4yW+kk0Lf#ko++@F*W4+c@c*Cw{W5{)?{?liUio497w)OY+-^6X?0fB; zJiS(ThEBt=Q{NY>YTS^!y}{1o_W!y~{EwPu3WH(-k|G}BNf8Iuu0*jD$ti2H_<{8*N`5Z~gl|xpqQ) z_uKr#zZA|z-?!*J`_mxOqW5U}(UgxSV)I2OAH5t=6Xql4pZxTmu~!6%RE{3diycG-%$pU45+sJwCh-qP@MyGNACaMC+#}8)BHB@zHYY2uYGJ{ z)_yqUA*ypeMjA%i^iF->%)qpL*`kf1C%4XopFeANZkqkl_!TB*xA=U@V&tWEzsWwB!e|neV?6?CC}G2dG#cq_gAq`ei>-8O>3r{>-s7K zAekImJfX?jZl2@2Z`Ynl7rvV}yLOLiz1RML%$zNmIuw&@ITt~wfFK38NSJ_uvmb28xlQX`}mnS?#${s7N&Z6@rzJ? zwabe$azc%4yW+kk0Lf#ko++@F*W4+c@c*Cw{W5{)?{?liUio497w)OY+-^6X?0fB; zJiS(ThEBt=Q{NY>YTS^!y}{1o_W!y~{EwPu3WH(-k|G}BNf8Iuu0*jD$ti2H_<{