Skip to content

Commit 370b85e

Browse files
authored
Merge branch 'dev-2.0' into refactor/strands-transpiler-pipeline
2 parents 5996f67 + 373ad88 commit 370b85e

30 files changed

Lines changed: 1106 additions & 393 deletions

File tree

docs/parameterData.json

Lines changed: 253 additions & 247 deletions
Large diffs are not rendered by default.

src/core/p5.Renderer3D.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ export class Renderer3D extends Renderer {
160160

161161
// clipping
162162
this._clipDepths = [];
163+
this._textContextSavedStack = [];
163164
this._isClipApplied = false;
164165
this._stencilTestOn = false;
165166

@@ -221,6 +222,8 @@ export class Renderer3D extends Renderer {
221222
// Used by beginShape/endShape functions to construct a p5.Geometry
222223
this.shapeBuilder = new ShapeBuilder(this);
223224

225+
this._largeTessellationAcknowledged = false;
226+
224227
this.geometryBufferCache = new GeometryBufferCache(this);
225228

226229
this.curStrokeCap = constants.ROUND;
@@ -477,10 +480,6 @@ export class Renderer3D extends Renderer {
477480
* combining them with `buildGeometry()` once and then drawing that will run
478481
* faster than repeatedly drawing the individual pieces.
479482
*
480-
* One can also draw shapes directly between
481-
* <a href="#/p5/beginGeometry">beginGeometry()</a> and
482-
* <a href="#/p5/endGeometry">endGeometry()</a> instead of using a callback
483-
* function.
484483
* @param {Function} callback A function that draws shapes.
485484
* @returns {p5.Geometry} The model that was built from the callback function.
486485
*/
@@ -1327,13 +1326,25 @@ export class Renderer3D extends Renderer {
13271326
return this;
13281327
}
13291328

1329+
push() {
1330+
super.push()
1331+
const saved = !!(this.states.textFont?.font);
1332+
if (saved) {
1333+
this.textDrawingContext().save()
1334+
}
1335+
this._textContextSavedStack.push(saved);
1336+
}
1337+
13301338
pop(...args) {
13311339
if (
13321340
this._clipDepths.length > 0 &&
13331341
this._pushPopDepth === this._clipDepths[this._clipDepths.length - 1]
13341342
) {
13351343
this._clearClip();
13361344
}
1345+
if (this._textContextSavedStack.pop()) {
1346+
this.textDrawingContext().restore()
1347+
}
13371348
super.pop(...args);
13381349
this._applyStencilTestIfClipping();
13391350
}
@@ -1995,6 +2006,10 @@ const webGPUAddonMessage = 'Add the WebGPU add-on to your project and pass WEBGP
19952006
function renderer3D(p5, fn) {
19962007
p5.Renderer3D = Renderer3D;
19972008

2009+
ShapeBuilder.prototype.friendlyErrorsDisabled = function() {
2010+
return Boolean(p5.disableFriendlyErrors);
2011+
};
2012+
19982013
/**
19992014
* Creates a <a href="#/p5/p5.StorageBuffer">`p5.StorageBuffer`</a>, which is
20002015
* a block of data that shaders can read from, and compute shaders

src/core/rendering.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ function rendering(p5, fn){
4545
* system variable to check what version is being used, or call
4646
* `setAttributes({ version: 1 })` to create a WebGL1 context.
4747
*
48+
* Note: In WebGPU mode, you must `await` this function.
49+
*
4850
* @method createCanvas
4951
* @param {Number} [width] width of the canvas. Defaults to 100.
5052
* @param {Number} [height] height of the canvas. Defaults to 100.
51-
* @param {(P2D|WEBGL|P2DHDR|WEBGPU)} [renderer] either P2D, WEBGL, or WEBGPU. Defaults to `P2D`.
53+
* @param {(P2D|WEBGL|P2DHDR)} [renderer] either P2D or WEBGL. Defaults to `P2D`.
5254
* @param {HTMLCanvasElement} [canvas] existing canvas element that should be used for the sketch.
5355
* @return {p5.Renderer} new `p5.Renderer` that holds the canvas.
5456
*
@@ -106,6 +108,14 @@ function rendering(p5, fn){
106108
* describe('A diagonal line drawn from top-left to bottom-right on a gray background.');
107109
* }
108110
*/
111+
/**
112+
* @method createCanvas
113+
* @param {Number} width
114+
* @param {Number} height
115+
* @param {WEBGPU} renderer
116+
* @param {HTMLCanvasElement} [canvas]
117+
* @return {Promise<p5.Renderer>}
118+
*/
109119
/**
110120
* @method createCanvas
111121
* @param {Number} [width]

src/shape/attributes.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,10 @@ function attributes(p5, fn){
107107
* In WebGL mode, `noSmooth()` causes all shapes to be drawn with jagged
108108
* (aliased) edges. The functions don't affect images or fonts.
109109
*
110+
* Note: In WebGPU mode, you must `await` this function.
111+
*
110112
* @method noSmooth
111-
* @chainable
113+
* @return {void|Promise<void>}
112114
*
113115
* @example
114116
* let heart;
@@ -162,10 +164,10 @@ function attributes(p5, fn){
162164
if ('imageSmoothingEnabled' in this.drawingContext) {
163165
this.drawingContext.imageSmoothingEnabled = false;
164166
}
167+
return this;
165168
} else {
166-
this.setAttributes('antialias', false);
169+
return this.setAttributes('antialias', false);
167170
}
168-
return this;
169171
};
170172

171173
/**

src/strands/p5.strands.js

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,17 @@ if (typeof p5 !== "undefined") {
213213

214214
/* ------------------------------------------------------------- */
215215
/**
216-
* @property {Object} worldInputs
216+
* @typedef {Object} WorldInputsHook
217+
* @property {any} position
218+
* @property {any} normal
219+
* @property {any} texCoord
220+
* @property {any} color
221+
* @property {function(): undefined} begin
222+
* @property {function(): undefined} end
223+
*/
224+
225+
/**
226+
* @property {WorldInputsHook} worldInputs
217227
* @beta
218228
* @description
219229
* A shader hook block that modifies the world-space properties of each vertex in a shader. This hook can be used inside <a href="#/p5/buildColorShader">`buildColorShader()`</a> and similar shader <a href="#/p5.Shader/modify">`modify()`</a> calls to customize vertex positions, normals, texture coordinates, and colors before rendering. Modifications happen between the `.begin()` and `.end()` methods of the hook. "World space" refers to the coordinate system of the 3D scene, before any camera or projection transformations are applied.
@@ -258,7 +268,22 @@ if (typeof p5 !== "undefined") {
258268
*/
259269

260270
/**
261-
* @property {Object} combineColors
271+
* @typedef {Object} CombineColorsHook
272+
* @property {any} baseColor
273+
* @property {any} diffuse
274+
* @property {any} ambientColor
275+
* @property {any} ambient
276+
* @property {any} specularColor
277+
* @property {any} specular
278+
* @property {any} emissive
279+
* @property {any} opacity
280+
* @property {function(): undefined} begin
281+
* @property {function(): undefined} end
282+
* @property {function(color: any): void} set
283+
*/
284+
285+
/**
286+
* @property {CombineColorsHook} combineColors
262287
* @beta
263288
* @description
264289
* A shader hook block that modifies how color components are combined in the fragment shader. This hook can be used inside <a href="#/p5/buildMaterialShader">`buildMaterialShader()`</a> and similar shader <a href="#/p5.Shader/modify">`modify()`</a> calls to control the final color output of a material. Modifications happen between the `.begin()` and `.end()` methods of the hook.
@@ -591,7 +616,26 @@ if (typeof p5 !== "undefined") {
591616
*/
592617

593618
/**
594-
* @property {Object} pixelInputs
619+
* @typedef {Object} PixelInputsHook
620+
* @property {any} normal
621+
* @property {any} texCoord
622+
* @property {any} ambientLight
623+
* @property {any} ambientMaterial
624+
* @property {any} specularMaterial
625+
* @property {any} emissiveMaterial
626+
* @property {any} color
627+
* @property {any} shininess
628+
* @property {any} metalness
629+
* @property {any} tangent
630+
* @property {any} center
631+
* @property {any} position
632+
* @property {any} strokeWeight
633+
* @property {function(): undefined} begin
634+
* @property {function(): undefined} end
635+
*/
636+
637+
/**
638+
* @property {PixelInputsHook} pixelInputs
595639
* @beta
596640
* @description
597641
* A shader hook block that modifies the properties of each pixel before the final color is calculated. This hook can be used inside <a href="#/p5/buildMaterialShader">`buildMaterialShader()`</a> and similar shader <a href="#/p5.Shader/modify">`modify()`</a> calls to adjust per-pixel data before lighting is applied. Modifications happen between the `.begin()` and `.end()` methods of the hook.
@@ -679,13 +723,23 @@ if (typeof p5 !== "undefined") {
679723
*/
680724

681725
/**
682-
* @property finalColor
726+
* @typedef {Object} FinalColorHook
727+
* @property {any} color
728+
* @property {any} texCoord
729+
* @property {function(): undefined} begin
730+
* @property {function(): undefined} end
731+
* @property {function(color: any): void} set
732+
*/
733+
734+
/**
735+
* @property {FinalColorHook} finalColor
683736
* @beta
684737
* @description
685738
* A shader hook block that modifies the final color of each pixel after all lighting is applied. This hook can be used inside <a href="#/p5/buildMaterialShader">`buildMaterialShader()`</a> and similar shader <a href="#/p5.Shader/modify">`modify()`</a> calls to adjust the color before it appears on the screen. Modifications happen between the `.begin()` and `.end()` methods of the hook.
686739
*
687740
* `finalColor` has the following properties:
688741
* - `color`: a four-component vector representing the pixel color (red, green, blue, alpha).
742+
* - `texCoord`: a two-component vector representing the texture coordinates (u, v)
689743
*
690744
* Call `.set()` on the hook with a vector with four components (red, green, blue, alpha) to update the final color.
691745
*
@@ -762,8 +816,18 @@ if (typeof p5 !== "undefined") {
762816
*/
763817

764818
/**
765-
* @property {Object} filterColor
766-
* @beta
819+
* @typedef {Object} FilterColorHook
820+
* @property {any} texCoord
821+
* @property {any} canvasSize
822+
* @property {any} texelSize
823+
* @property {any} canvasContent
824+
* @property {function(): undefined} begin
825+
* @property {function(): undefined} end
826+
* @property {function(color: any): void} set
827+
*/
828+
829+
/**
830+
* @property {FilterColorHook} filterColor
767831
* @description
768832
* A shader hook block that sets the color for each pixel in a filter shader. This hook can be used inside <a href="#/p5/buildFilterShader">`buildFilterShader()`</a> to control the output color for each pixel.
769833
*
@@ -807,7 +871,17 @@ if (typeof p5 !== "undefined") {
807871
*/
808872

809873
/**
810-
* @property {Object} objectInputs
874+
* @typedef {Object} ObjectInputsHook
875+
* @property {any} position
876+
* @property {any} normal
877+
* @property {any} texCoord
878+
* @property {any} color
879+
* @property {function(): undefined} begin
880+
* @property {function(): undefined} end
881+
*/
882+
883+
/**
884+
* @property {ObjectInputsHook} objectInputs
811885
* @beta
812886
* @description
813887
* A shader hook block to modify the properties of each vertex before any transformations are applied. This hook can be used inside <a href="#/p5/buildMaterialShader">`buildMaterialShader()`</a> and similar shader <a href="#/p5.Shader/modify">`modify()`</a> calls to customize vertex positions, normals, texture coordinates, and colors before rendering. Modifications happen between the `.begin()` and `.end()` methods of the hook. "Object space" refers to the coordinate system of the 3D scene before any transformations, cameras, or projection transformations are applied.
@@ -849,7 +923,17 @@ if (typeof p5 !== "undefined") {
849923
*/
850924

851925
/**
852-
* @property {Object} cameraInputs
926+
* @typedef {Object} CameraInputsHook
927+
* @property {any} position
928+
* @property {any} normal
929+
* @property {any} texCoord
930+
* @property {any} color
931+
* @property {function(): undefined} begin
932+
* @property {function(): undefined} end
933+
*/
934+
935+
/**
936+
* @property {CameraInputsHook} cameraInputs
853937
* @beta
854938
* @description
855939
* A shader hook block that adjusts vertex properties from the perspective of the camera. This hook can be used inside <a href="#/p5/buildMaterialShader">`buildMaterialShader()`</a> and similar shader <a href="#/p5.Shader/modify">`modify()`</a> calls to customize vertex positions, normals, texture coordinates, and colors before rendering. "Camera space" refers to the coordinate system of the 3D scene after transformations have been applied, seen relative to the camera.

src/strands/strands_transpiler.js

Lines changed: 33 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,35 @@ function replaceIdentifierReferences(node, oldName, newName) {
259259
return replaceInNode(node);
260260
}
261261

262+
// Shared handler for both BinaryExpression and LogicalExpression —
263+
// both follow the same operator-to-method-call transformation pattern.
264+
function transformBinaryOrLogical(node, state, ancestors) {
265+
if (ancestors.some(a => nodeIsUniform(a) || nodeIsUniformCallbackFn(a, state.uniformCallbackNames))) {
266+
return;
267+
}
268+
const unsafeTypes = ['Literal', 'ArrayExpression', 'Identifier'];
269+
if (unsafeTypes.includes(node.left.type)) {
270+
node.left = {
271+
type: 'CallExpression',
272+
callee: {
273+
type: 'Identifier',
274+
name: '__p5.strandsNode',
275+
},
276+
arguments: [node.left]
277+
};
278+
}
279+
node.type = 'CallExpression';
280+
node.callee = {
281+
type: 'MemberExpression',
282+
object: node.left,
283+
property: {
284+
type: 'Identifier',
285+
name: replaceBinaryOperator(node.operator),
286+
},
287+
};
288+
node.arguments = [node.right];
289+
}
290+
262291
const ASTCallbacks = {
263292
UnaryExpression(node, state, ancestors) {
264293
if (ancestors.some(a => nodeIsUniform(a) || nodeIsUniformCallbackFn(a, state.uniformCallbackNames))) {
@@ -533,72 +562,10 @@ const ASTCallbacks = {
533562
}
534563
}
535564
},
536-
BinaryExpression(node, state, ancestors) {
537-
// Don't convert uniform default values to node methods, as
538-
// they should be evaluated at runtime, not compiled.
539-
if (ancestors.some(a => nodeIsUniform(a) || nodeIsUniformCallbackFn(a, state.uniformCallbackNames))) {
540-
return;
541-
}
542-
// If the left hand side of an expression is one of these types,
543-
// we should construct a node from it.
544-
const unsafeTypes = ['Literal', 'ArrayExpression', 'Identifier'];
545-
if (unsafeTypes.includes(node.left.type)) {
546-
const leftReplacementNode = {
547-
type: 'CallExpression',
548-
callee: {
549-
type: 'Identifier',
550-
name: '__p5.strandsNode',
551-
},
552-
arguments: [node.left]
553-
}
554-
node.left = leftReplacementNode;
555-
}
556-
// Replace the binary operator with a call expression
557-
// in other words a call to BaseNode.mult(), .div() etc.
558-
node.type = 'CallExpression';
559-
node.callee = {
560-
type: 'MemberExpression',
561-
object: node.left,
562-
property: {
563-
type: 'Identifier',
564-
name: replaceBinaryOperator(node.operator),
565-
},
566-
};
567-
node.arguments = [node.right];
568-
},
569-
LogicalExpression(node, state, ancestors) {
570-
// Don't convert uniform default values to node methods, as
571-
// they should be evaluated at runtime, not compiled.
572-
if (ancestors.some(a => nodeIsUniform(a) || nodeIsUniformCallbackFn(a, state.uniformCallbackNames))) {
573-
return;
574-
}
575-
// If the left hand side of an expression is one of these types,
576-
// we should construct a node from it.
577-
const unsafeTypes = ['Literal', 'ArrayExpression', 'Identifier'];
578-
if (unsafeTypes.includes(node.left.type)) {
579-
const leftReplacementNode = {
580-
type: 'CallExpression',
581-
callee: {
582-
type: 'Identifier',
583-
name: '__p5.strandsNode',
584-
},
585-
arguments: [node.left]
586-
}
587-
node.left = leftReplacementNode;
588-
}
589-
// Replace the logical operator with a call expression
590-
// in other words a call to BaseNode.or(), .and() etc.
591-
node.type = 'CallExpression';
592-
node.callee = {
593-
type: 'MemberExpression',
594-
object: node.left,
595-
property: {
596-
type: 'Identifier',
597-
name: replaceBinaryOperator(node.operator),
598-
},
599-
};
600-
node.arguments = [node.right];
601-
},
565+
BinaryExpression: transformBinaryOrLogical,
566+
LogicalExpression: transformBinaryOrLogical,
567+
568+
602569
ConditionalExpression(node, state, ancestors) {
603570
if (ancestors.some(a => nodeIsUniform(a) || nodeIsUniformCallbackFn(a, state.uniformCallbackNames))) {
604571
return;

0 commit comments

Comments
 (0)