Skip to content

Commit 1e0e11e

Browse files
authored
Merge branch 'dev-2.0' into Adding-millis()
2 parents 2057fe8 + 8bf8b6b commit 1e0e11e

File tree

18 files changed

+354
-41
lines changed

18 files changed

+354
-41
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"test/**/*.js": "eslint",
2121
"utils/**/*.{js,mjs}": "eslint"
2222
},
23-
"version": "2.2.1",
23+
"version": "2.2.2-rc.0",
2424
"dependencies": {
2525
"@davepagurek/bezier-path": "^0.0.7",
2626
"@japont/unicode-range": "^1.0.0",

src/color/creating_reading.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,11 +1384,11 @@ function creatingReading(p5, fn){
13841384
* values. 0 is equal to the first color, 0.1 is very near the first color,
13851385
* 0.5 is halfway between the two colors, and so on. Negative numbers are set
13861386
* to 0. Numbers greater than 1 are set to 1. This differs from the behavior of
1387-
* <a href="#/lerp">lerp</a>. It's necessary because numbers outside of the
1387+
* <a href="#/p5/lerp">lerp</a>. It's necessary because numbers outside of the
13881388
* interval [0, 1] will produce strange and unexpected colors.
13891389
*
13901390
* The way that colors are interpolated depends on the current
1391-
* <a href="#/colorMode">colorMode()</a>.
1391+
* <a href="#/p5/colorMode">colorMode()</a>.
13921392
*
13931393
* @method lerpColor
13941394
* @param {p5.Color} c1 interpolate from this color.

src/strands/ir_builders.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export function unaryOpNode(strandsContext, nodeOrValue, opCode) {
4343
const { dag, cfg } = strandsContext;
4444
let dependsOn;
4545
let node;
46-
if (nodeOrValue instanceof StrandsNode) {
46+
if (nodeOrValue?.isStrandsNode) {
4747
node = nodeOrValue;
4848
} else {
4949
const { id, dimension } = primitiveConstructorNode(strandsContext, { baseType: BaseType.FLOAT, dimension: null }, nodeOrValue);
@@ -257,6 +257,20 @@ export function constructTypeFromIDs(strandsContext, typeInfo, strandsNodesArray
257257

258258
export function primitiveConstructorNode(strandsContext, typeInfo, dependsOn) {
259259
const cfg = strandsContext.cfg;
260+
dependsOn = (Array.isArray(dependsOn) ? dependsOn : [dependsOn])
261+
.flat(Infinity)
262+
.map(a => {
263+
if (
264+
a.isStrandsNode &&
265+
a.typeInfo().baseType === BaseType.INT &&
266+
// TODO: handle ivec inputs instead of just int scalars
267+
a.typeInfo().dimension === 1
268+
) {
269+
return castToFloat(strandsContext, a);
270+
} else {
271+
return a;
272+
}
273+
});
260274
const { mappedDependencies, inferredTypeInfo } = mapPrimitiveDepsToIDs(strandsContext, typeInfo, dependsOn);
261275

262276
const finalType = {
@@ -272,6 +286,24 @@ export function primitiveConstructorNode(strandsContext, typeInfo, dependsOn) {
272286
return { id, dimension: finalType.dimension, components: mappedDependencies };
273287
}
274288

289+
export function castToFloat(strandsContext, dep) {
290+
const { id, dimension } = functionCallNode(
291+
strandsContext,
292+
strandsContext.backend.getTypeName('float', dep.typeInfo().dimension),
293+
[dep],
294+
{
295+
overloads: [{
296+
params: [dep.typeInfo()],
297+
returnType: {
298+
...dep.typeInfo(),
299+
baseType: BaseType.FLOAT,
300+
},
301+
}],
302+
}
303+
);
304+
return createStrandsNode(id, dimension, strandsContext);
305+
}
306+
275307
export function structConstructorNode(strandsContext, structTypeInfo, rawUserArgs) {
276308
const { cfg, dag } = strandsContext;
277309
const { identifer, properties } = structTypeInfo;
@@ -491,7 +523,7 @@ export function swizzleTrap(id, dimension, strandsContext, onRebind) {
491523
// This may not be the most efficient way, as we swizzle each component individually,
492524
// so that .xyz becomes .x, .y, .z
493525
let scalars = [];
494-
if (value instanceof StrandsNode) {
526+
if (value?.isStrandsNode) {
495527
if (value.dimension === 1) {
496528
scalars = Array(chars.length).fill(value);
497529
} else if (value.dimension === chars.length) {

src/strands/strands_api.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ export function initGlobalStrandsAPI(p5, fn, strandsContext) {
167167
}
168168

169169
// Convert value to a StrandsNode if it isn't already
170-
const valueNode = value instanceof StrandsNode ? value : p5.strandsNode(value);
170+
const valueNode = value?.isStrandsNode ? value : p5.strandsNode(value);
171171

172172
// Create a new CFG block for the early return
173173
const earlyReturnBlockID = CFG.createBasicBlock(cfg, BlockType.DEFAULT);
@@ -398,12 +398,17 @@ export function initGlobalStrandsAPI(p5, fn, strandsContext) {
398398
fn[typeInfo.fnName] = function(...args) {
399399
if (strandsContext.active) {
400400
if (args.length === 1 && args[0].dimension && args[0].dimension === typeInfo.dimension) {
401-
const { id, dimension } = build.functionCallNode(strandsContext, typeInfo.fnName, args, {
402-
overloads: [{
403-
params: [args[0].typeInfo()],
404-
returnType: typeInfo,
405-
}]
406-
});
401+
const { id, dimension } = build.functionCallNode(
402+
strandsContext,
403+
strandsContext.backend.getTypeName(typeInfo.baseType, typeInfo.dimension),
404+
args,
405+
{
406+
overloads: [{
407+
params: [args[0].typeInfo()],
408+
returnType: typeInfo,
409+
}]
410+
}
411+
);
407412
return createStrandsNode(id, dimension, strandsContext);
408413
} else {
409414
// For vector types with a single argument, repeat it for each component
@@ -460,7 +465,7 @@ function createHookArguments(strandsContext, parameters){
460465
const oldDependsOn = dag.dependsOn[structNode.id];
461466
const newDependsOn = [...oldDependsOn];
462467
let newValueID;
463-
if (val instanceof StrandsNode) {
468+
if (val?.isStrandsNode) {
464469
newValueID = val.id;
465470
}
466471
else {
@@ -492,7 +497,7 @@ function createHookArguments(strandsContext, parameters){
492497
return args;
493498
}
494499
function enforceReturnTypeMatch(strandsContext, expectedType, returned, hookName) {
495-
if (!(returned instanceof StrandsNode)) {
500+
if (!(returned?.isStrandsNode)) {
496501
// try {
497502
const result = build.primitiveConstructorNode(strandsContext, expectedType, returned);
498503
return result.id;
@@ -607,7 +612,7 @@ export function createShaderHooksFunctions(strandsContext, fn, shader) {
607612
const handleRetVal = (retNode) => {
608613
if(isStructType(expectedReturnType)) {
609614
const expectedStructType = structType(expectedReturnType);
610-
if (retNode instanceof StrandsNode) {
615+
if (retNode?.isStrandsNode) {
611616
const returnedNode = getNodeDataFromID(strandsContext.dag, retNode.id);
612617
if (returnedNode.baseType !== expectedStructType.typeName) {
613618
const receivedTypeName = returnedNode.baseType || 'undefined';

src/strands/strands_for.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ export class StrandsFor {
309309
let initialVar = this.initialCb();
310310

311311
// Convert to StrandsNode if it's not already one
312-
if (!(initialVar instanceof StrandsNode)) {
312+
if (!(initialVar?.isStrandsNode)) {
313313
const { id, dimension } = primitiveConstructorNode(this.strandsContext, { baseType: BaseType.FLOAT, dimension: 1 }, initialVar);
314314
initialVar = createStrandsNode(id, dimension, this.strandsContext);
315315
}

src/strands/strands_node.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class StrandsNode {
4040
const baseType = orig?.baseType ?? BaseType.FLOAT;
4141

4242
let newValueID;
43-
if (value instanceof StrandsNode) {
43+
if (value?.isStrandsNode) {
4444
newValueID = value.id;
4545
} else {
4646
const newVal = primitiveConstructorNode(
@@ -95,7 +95,7 @@ export class StrandsNode {
9595
const baseType = orig?.baseType ?? BaseType.FLOAT;
9696

9797
let newValueID;
98-
if (value instanceof StrandsNode) {
98+
if (value?.isStrandsNode) {
9999
newValueID = value.id;
100100
} else {
101101
const newVal = primitiveConstructorNode(

src/webgl/material.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -732,15 +732,17 @@ function material(p5, fn) {
732732
* @beta
733733
* @submodule p5.strands
734734
* @param {Function} callback A function building a p5.strands shader.
735+
* @param {Object} [scope] An optional scope object passed to .modify().
735736
* @returns {p5.Shader} The material shader
736737
*/
737738
/**
738739
* @method buildFilterShader
739740
* @param {Object} hooks An object specifying p5.strands hooks in GLSL.
741+
* @param {Object} [scope] An optional scope object passed to .modify().
740742
* @returns {p5.Shader} The material shader
741743
*/
742-
fn.buildFilterShader = function (callback) {
743-
return this.baseFilterShader().modify(callback);
744+
fn.buildFilterShader = function (callback, scope) {
745+
return this.baseFilterShader().modify(callback, scope);
744746
};
745747

746748
/**
@@ -1560,15 +1562,17 @@ function material(p5, fn) {
15601562
* @submodule p5.strands
15611563
* @beta
15621564
* @param {Function} callback A function building a p5.strands shader.
1565+
* @param {Object} [scope] An optional scope object passed to .modify().
15631566
* @returns {p5.Shader} The material shader.
15641567
*/
15651568
/**
15661569
* @method buildMaterialShader
15671570
* @param {Object} hooks An object specifying p5.strands hooks in GLSL.
1571+
* @param {Object} [scope] An optional scope object passed to .modify().
15681572
* @returns {p5.Shader} The material shader.
15691573
*/
1570-
fn.buildMaterialShader = function (cb) {
1571-
return this.baseMaterialShader().modify(cb);
1574+
fn.buildMaterialShader = function (cb, scope) {
1575+
return this.baseMaterialShader().modify(cb, scope);
15721576
};
15731577

15741578
/**
@@ -1776,15 +1780,17 @@ function material(p5, fn) {
17761780
* @submodule p5.strands
17771781
* @beta
17781782
* @param {Function} callback A function building a p5.strands shader.
1783+
* @param {Object} [scope] An optional scope object passed to .modify().
17791784
* @returns {p5.Shader} The normal shader.
17801785
*/
17811786
/**
17821787
* @method buildNormalShader
17831788
* @param {Object} hooks An object specifying p5.strands hooks in GLSL.
1789+
* @param {Object} [scope] An optional scope object passed to .modify().
17841790
* @returns {p5.Shader} The normal shader.
17851791
*/
1786-
fn.buildNormalShader = function (cb) {
1787-
return this.baseNormalShader().modify(cb);
1792+
fn.buildNormalShader = function (cb, scope) {
1793+
return this.baseNormalShader().modify(cb, scope);
17881794
};
17891795

17901796
/**
@@ -1940,15 +1946,17 @@ function material(p5, fn) {
19401946
* @submodule p5.strands
19411947
* @beta
19421948
* @param {Function} callback A function building a p5.strands shader.
1949+
* @param {Object} [scope] An optional scope object passed to .modify().
19431950
* @returns {p5.Shader} The color shader.
19441951
*/
19451952
/**
19461953
* @method buildColorShader
19471954
* @param {Object} hooks An object specifying p5.strands hooks in GLSL.
1955+
* @param {Object} [scope] An optional scope object passed to .modify().
19481956
* @returns {p5.Shader} The color shader.
19491957
*/
1950-
fn.buildColorShader = function (cb) {
1951-
return this.baseColorShader().modify(cb);
1958+
fn.buildColorShader = function (cb, scope) {
1959+
return this.baseColorShader().modify(cb, scope);
19521960
};
19531961

19541962
/**
@@ -2195,15 +2203,17 @@ function material(p5, fn) {
21952203
* @submodule p5.strands
21962204
* @beta
21972205
* @param {Function} callback A function building a p5.strands shader.
2206+
* @param {Object} [scope] An optional scope object passed to .modify().
21982207
* @returns {p5.Shader} The stroke shader.
21992208
*/
22002209
/**
22012210
* @method buildStrokeShader
22022211
* @param {Object} hooks An object specifying p5.strands hooks in GLSL.
2212+
* @param {Object} [scope] An optional scope object passed to .modify().
22032213
* @returns {p5.Shader} The stroke shader.
22042214
*/
2205-
fn.buildStrokeShader = function (cb) {
2206-
return this.baseStrokeShader().modify(cb);
2215+
fn.buildStrokeShader = function (cb, scope) {
2216+
return this.baseStrokeShader().modify(cb, scope);
22072217
};
22082218

22092219
/**

src/webgpu/p5.RendererWebGPU.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1904,7 +1904,7 @@ function rendererWebGPU(p5, fn) {
19041904

19051905
getNextBindingIndex({ vert, frag }, group = 0) {
19061906
// Get the highest binding index in the specified group and return the next available
1907-
const samplerRegex = /@group\((\d+)\)\s*@binding\((\d+)\)\s*var\s+(\w+)\s*:\s*(texture_2d<f32>|sampler|uniform)/g;
1907+
const samplerRegex = /@group\((\d+)\)\s*@binding\((\d+)\)\s*var(?:<uniform>)?\s+(\w+)\s*:\s*(texture_2d<f32>|sampler|uniform|\w+)/g;
19081908
let maxBindingIndex = -1;
19091909

19101910
for (const [src, visibility] of [
@@ -2254,6 +2254,9 @@ function rendererWebGPU(p5, fn) {
22542254
// Inject hook uniforms as a separate struct at a new binding
22552255
let hookUniformFields = '';
22562256
for (const key in shader.hooks.uniforms) {
2257+
// Skip textures, they don't get added to structs
2258+
if (key.endsWith(': sampler2D')) continue;
2259+
22572260
// WGSL format: "name: type"
22582261
hookUniformFields += ` ${key},\n`;
22592262
}

src/webgpu/strands_wgslBackend.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,11 @@ export const wgslBackend = {
223223
return primitiveTypeName;
224224
},
225225
generateHookUniformKey(name, typeInfo) {
226-
// For sampler2D types, we don't add them to the uniform struct
227-
// Instead, they become separate texture and sampler bindings
226+
// For sampler2D types, we don't add them to the uniform struct,
227+
// but we still need them in the shader's hooks object so that
228+
// they can be set by users.
228229
if (typeInfo.baseType === 'sampler2D') {
229-
return null; // Signal that this should not be added to uniform struct
230+
return `${name}: sampler2D`; // Signal that this should not be added to uniform struct
230231
}
231232
return `${name}: ${this.getTypeName(typeInfo.baseType, typeInfo.dimension)}`;
232233
},

0 commit comments

Comments
 (0)