p5 2.2.3 → 2.3.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accessibility/color_namer.js +9 -11
- package/dist/accessibility/describe.js +0 -1
- package/dist/accessibility/gridOutput.js +0 -1
- package/dist/accessibility/index.js +9 -10
- package/dist/accessibility/outputs.js +0 -1
- package/dist/accessibility/textOutput.js +0 -1
- package/dist/app.js +11 -10
- package/dist/app.node.js +122 -0
- package/dist/color/color_conversion.js +9 -11
- package/dist/color/creating_reading.js +1 -1
- package/dist/color/index.js +2 -2
- package/dist/color/p5.Color.js +1 -1
- package/dist/color/setting.js +25 -12
- package/dist/{constants-BdTiYOQI.js → constants-0wkVUfqa.js} +2 -2
- package/dist/core/States.js +1 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/environment.js +28 -29
- package/dist/core/filterShaders.js +1 -1
- package/dist/core/friendly_errors/fes_core.js +9 -8
- package/dist/core/friendly_errors/file_errors.js +1 -2
- package/dist/core/friendly_errors/index.js +1 -1
- package/dist/core/friendly_errors/param_validator.js +737 -640
- package/dist/core/friendly_errors/sketch_verifier.js +1 -1
- package/dist/core/friendly_errors/stacktrace.js +0 -1
- package/dist/core/helpers.js +3 -4
- package/dist/core/init.js +24 -21
- package/dist/core/internationalization.js +1 -1
- package/dist/core/legacy.js +9 -11
- package/dist/core/main.js +9 -10
- package/dist/core/p5.Graphics.js +5 -5
- package/dist/core/p5.Renderer.js +3 -3
- package/dist/core/p5.Renderer2D.js +9 -10
- package/dist/core/p5.Renderer3D.js +5 -5
- package/dist/core/rendering.js +5 -5
- package/dist/core/structure.js +0 -1
- package/dist/core/transform.js +7 -16
- package/dist/{creating_reading-C7hu6sg1.js → creating_reading-DLkHH80h.js} +11 -8
- package/dist/data/local_storage.js +0 -1
- package/dist/dom/dom.js +2 -3
- package/dist/dom/index.js +2 -2
- package/dist/dom/p5.Element.js +2 -2
- package/dist/dom/p5.MediaElement.js +2 -2
- package/dist/events/acceleration.js +5 -3
- package/dist/events/keyboard.js +0 -1
- package/dist/events/pointer.js +0 -2
- package/dist/image/const.js +1 -1
- package/dist/image/filterRenderer2D.js +19 -12
- package/dist/image/image.js +5 -5
- package/dist/image/index.js +5 -5
- package/dist/image/loading_displaying.js +5 -5
- package/dist/image/p5.Image.js +3 -3
- package/dist/image/pixels.js +0 -1
- package/dist/io/files.js +5 -5
- package/dist/io/index.js +5 -5
- package/dist/io/p5.Table.js +0 -1
- package/dist/io/p5.TableRow.js +0 -1
- package/dist/io/p5.XML.js +0 -1
- package/dist/{ir_builders-Cd6rU9Vm.js → ir_builders-C2ebb6Lu.js} +234 -1
- package/dist/{main-H_nu4eDs.js → main-D2kqeMXM.js} +107 -136
- package/dist/math/Matrices/Matrix.js +1 -1
- package/dist/math/Matrices/MatrixNumjs.js +1 -1
- package/dist/math/calculation.js +0 -1
- package/dist/math/index.js +3 -1
- package/dist/math/math.js +3 -17
- package/dist/math/noise.js +0 -1
- package/dist/math/p5.Matrix.js +1 -2
- package/dist/math/p5.Vector.js +237 -279
- package/dist/math/patch-vector.js +75 -0
- package/dist/math/random.js +0 -1
- package/dist/math/trigonometry.js +3 -4
- package/dist/{p5.Renderer-BmD2P6Wv.js → p5.Renderer-CQI8PO1F.js} +31 -24
- package/dist/{rendering-CC8JNTwG.js → rendering-ltTIxpF2.js} +732 -44
- package/dist/shape/2d_primitives.js +1 -4
- package/dist/shape/attributes.js +43 -8
- package/dist/shape/curves.js +0 -1
- package/dist/shape/custom_shapes.js +260 -5
- package/dist/shape/index.js +2 -2
- package/dist/shape/vertex.js +0 -2
- package/dist/strands/ir_builders.js +1 -1
- package/dist/strands/ir_types.js +5 -1
- package/dist/strands/p5.strands.js +286 -31
- package/dist/strands/strands_api.js +179 -8
- package/dist/strands/strands_codegen.js +26 -8
- package/dist/strands/strands_conditionals.js +1 -1
- package/dist/strands/strands_for.js +1 -1
- package/dist/strands/strands_node.js +1 -1
- package/dist/strands/strands_ternary.js +56 -0
- package/dist/strands/strands_transpiler.js +416 -251
- package/dist/strands_glslBackend-i-ReKgZo.js +423 -0
- package/dist/type/index.js +3 -3
- package/dist/type/lib/Typr.js +1 -1
- package/dist/type/p5.Font.js +3 -3
- package/dist/type/textCore.js +31 -24
- package/dist/utilities/conversion.js +0 -1
- package/dist/utilities/time_date.js +0 -1
- package/dist/utilities/utility_functions.js +0 -1
- package/dist/webgl/3d_primitives.js +5 -5
- package/dist/webgl/GeometryBuilder.js +1 -1
- package/dist/webgl/ShapeBuilder.js +26 -1
- package/dist/webgl/enums.js +1 -1
- package/dist/webgl/index.js +8 -9
- package/dist/webgl/interaction.js +8 -4
- package/dist/webgl/light.js +5 -5
- package/dist/webgl/loading.js +60 -21
- package/dist/webgl/material.js +5 -5
- package/dist/webgl/p5.Camera.js +5 -5
- package/dist/webgl/p5.Framebuffer.js +5 -5
- package/dist/webgl/p5.Geometry.js +3 -5
- package/dist/webgl/p5.Quat.js +1 -1
- package/dist/webgl/p5.RendererGL.js +17 -21
- package/dist/webgl/p5.Shader.js +129 -36
- package/dist/webgl/p5.Texture.js +5 -5
- package/dist/webgl/strands_glslBackend.js +5 -386
- package/dist/webgl/text.js +5 -5
- package/dist/webgl/utils.js +5 -5
- package/dist/webgl2Compatibility-DA7DLMuq.js +7 -0
- package/dist/webgpu/index.js +7 -3
- package/dist/webgpu/p5.RendererWebGPU.js +1146 -180
- package/dist/webgpu/shaders/color.js +1 -1
- package/dist/webgpu/shaders/compute.js +32 -0
- package/dist/webgpu/shaders/functions/randomComputeWGSL.js +31 -0
- package/dist/webgpu/shaders/functions/randomVertWGSL.js +30 -0
- package/dist/webgpu/shaders/functions/randomWGSL.js +30 -0
- package/dist/webgpu/shaders/line.js +1 -1
- package/dist/webgpu/shaders/material.js +3 -3
- package/dist/webgpu/strands_wgslBackend.js +137 -15
- package/lib/p5.esm.js +4092 -1950
- package/lib/p5.esm.min.js +1 -1
- package/lib/p5.js +4092 -1950
- package/lib/p5.min.js +1 -1
- package/lib/p5.webgpu.esm.js +1748 -306
- package/lib/p5.webgpu.js +1747 -305
- package/lib/p5.webgpu.min.js +1 -1
- package/package.json +6 -1
- package/types/global.d.ts +4182 -2441
- package/types/p5.d.ts +2776 -1675
- package/dist/noise3DGLSL-Bwrdi4gi.js +0 -9
|
@@ -119,7 +119,7 @@ ${uniforms}
|
|
|
119
119
|
@fragment
|
|
120
120
|
fn main(input: FragmentInput) -> @location(0) vec4<f32> {
|
|
121
121
|
HOOK_beforeFragment();
|
|
122
|
-
var outColor = HOOK_getFinalColor(input.vColor);
|
|
122
|
+
var outColor = HOOK_getFinalColor(input.vColor, input.vVertTexCoord);
|
|
123
123
|
outColor = vec4<f32>(outColor.rgb * outColor.a, outColor.a);
|
|
124
124
|
HOOK_afterFragment();
|
|
125
125
|
return outColor;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const baseComputeShader = `
|
|
2
|
+
struct ComputeUniforms {
|
|
3
|
+
uTotalCount: vec3<i32>,
|
|
4
|
+
uPhysicalCount: vec3<i32>,
|
|
5
|
+
}
|
|
6
|
+
@group(0) @binding(0) var<uniform> uniforms: ComputeUniforms;
|
|
7
|
+
|
|
8
|
+
@compute @workgroup_size(8, 8, 1)
|
|
9
|
+
fn main(
|
|
10
|
+
@builtin(global_invocation_id) globalId: vec3<u32>,
|
|
11
|
+
@builtin(local_invocation_id) localId: vec3<u32>,
|
|
12
|
+
@builtin(workgroup_id) workgroupId: vec3<u32>,
|
|
13
|
+
@builtin(local_invocation_index) localIndex: u32
|
|
14
|
+
) {
|
|
15
|
+
let totalIterations = u32(uniforms.uTotalCount.x) * u32(uniforms.uTotalCount.y) * u32(uniforms.uTotalCount.z);
|
|
16
|
+
let physicalId = globalId.x + globalId.y * (u32(uniforms.uPhysicalCount.x)) + globalId.z * (u32(uniforms.uPhysicalCount.x) * u32(uniforms.uPhysicalCount.y));
|
|
17
|
+
|
|
18
|
+
if (physicalId >= totalIterations) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
var index = vec3<i32>(0);
|
|
23
|
+
index.x = i32(physicalId % u32(uniforms.uTotalCount.x));
|
|
24
|
+
let remainingY = physicalId / u32(uniforms.uTotalCount.x);
|
|
25
|
+
index.y = i32(remainingY % u32(uniforms.uTotalCount.y));
|
|
26
|
+
index.z = i32(remainingY / u32(uniforms.uTotalCount.y));
|
|
27
|
+
|
|
28
|
+
HOOK_iteration(index);
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
export { baseComputeShader };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// _p5_hash: "Hash without Sine" by Dave Hoskins (https://www.shadertoy.com/view/4djSRW)
|
|
2
|
+
// Mixing constants: R₂ sequence by Martin Roberts (https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/)
|
|
3
|
+
// α₁ = 1/φ₂ = 0.7548776662 (plastic constant reciprocal)
|
|
4
|
+
// α₂ = 1/φ₂² = 0.5698402910
|
|
5
|
+
// 1/φ = 0.6180339887 (golden ratio conjugate)
|
|
6
|
+
//
|
|
7
|
+
// Compute shader version: invocationId is passed in from main via @builtin(global_invocation_id).
|
|
8
|
+
|
|
9
|
+
var randomComputeWGSL = `
|
|
10
|
+
var<private> _p5_randomCallIndex: i32 = 0;
|
|
11
|
+
|
|
12
|
+
fn _p5_hash(p: vec3<f32>) -> f32 {
|
|
13
|
+
var p3 = fract(p * vec3<f32>(0.1031, 0.1030, 0.0973));
|
|
14
|
+
p3 = p3 + dot(p3, p3.yxz + 33.33);
|
|
15
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fn random(seed: f32, invocationId: vec3<u32>) -> f32 {
|
|
19
|
+
let id = vec3<f32>(invocationId);
|
|
20
|
+
let callIndex = f32(_p5_randomCallIndex);
|
|
21
|
+
_p5_randomCallIndex = _p5_randomCallIndex + 1;
|
|
22
|
+
let s = fract(seed * 0.7548776662);
|
|
23
|
+
return _p5_hash(vec3<f32>(
|
|
24
|
+
id.x + s,
|
|
25
|
+
id.y + callIndex * 0.5698402910,
|
|
26
|
+
id.z + s + callIndex * 0.6180339887
|
|
27
|
+
));
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
export { randomComputeWGSL as default };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// _p5_hash: "Hash without Sine" by Dave Hoskins (https://www.shadertoy.com/view/4djSRW)
|
|
2
|
+
// Mixing constants: R₂ sequence by Martin Roberts (https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/)
|
|
3
|
+
// α₁ = 1/φ₂ = 0.7548776662 (plastic constant reciprocal)
|
|
4
|
+
// α₂ = 1/φ₂² = 0.5698402910
|
|
5
|
+
// 1/φ = 0.6180339887 (golden ratio conjugate)
|
|
6
|
+
//
|
|
7
|
+
// Vertex shader version: vertexId is passed in from main via @builtin(vertex_index).
|
|
8
|
+
|
|
9
|
+
var randomVertWGSL = `
|
|
10
|
+
var<private> _p5_randomCallIndex: i32 = 0;
|
|
11
|
+
|
|
12
|
+
fn _p5_hash(p: vec3<f32>) -> f32 {
|
|
13
|
+
var p3 = fract(p * vec3<f32>(0.1031, 0.1030, 0.0973));
|
|
14
|
+
p3 = p3 + dot(p3, p3.yxz + 33.33);
|
|
15
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fn random(seed: f32, vertexId: f32) -> f32 {
|
|
19
|
+
let callIndex = f32(_p5_randomCallIndex);
|
|
20
|
+
_p5_randomCallIndex = _p5_randomCallIndex + 1;
|
|
21
|
+
let s = fract(seed * 0.7548776662);
|
|
22
|
+
return _p5_hash(vec3<f32>(
|
|
23
|
+
vertexId + s,
|
|
24
|
+
vertexId * 0.5698402910 + callIndex * 0.6180339887,
|
|
25
|
+
s + callIndex * 0.7548776662
|
|
26
|
+
));
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
export { randomVertWGSL as default };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// _p5_hash: "Hash without Sine" by Dave Hoskins (https://www.shadertoy.com/view/4djSRW)
|
|
2
|
+
// Mixing constants: R₂ sequence by Martin Roberts (https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/)
|
|
3
|
+
// α₁ = 1/φ₂ = 0.7548776662 (plastic constant reciprocal)
|
|
4
|
+
// α₂ = 1/φ₂² = 0.5698402910
|
|
5
|
+
// 1/φ = 0.6180339887 (golden ratio conjugate)
|
|
6
|
+
//
|
|
7
|
+
// Fragment shader version: pixelCoord is passed in from main via @builtin(position).
|
|
8
|
+
|
|
9
|
+
var randomWGSL = `
|
|
10
|
+
var<private> _p5_randomCallIndex: i32 = 0;
|
|
11
|
+
|
|
12
|
+
fn _p5_hash(p: vec3<f32>) -> f32 {
|
|
13
|
+
var p3 = fract(p * vec3<f32>(0.1031, 0.1030, 0.0973));
|
|
14
|
+
p3 = p3 + dot(p3, p3.yxz + 33.33);
|
|
15
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fn random(seed: f32, pixelCoord: vec2<f32>) -> f32 {
|
|
19
|
+
let callIndex = f32(_p5_randomCallIndex);
|
|
20
|
+
_p5_randomCallIndex = _p5_randomCallIndex + 1;
|
|
21
|
+
let s = fract(seed * 0.7548776662);
|
|
22
|
+
return _p5_hash(vec3<f32>(
|
|
23
|
+
pixelCoord.x + s,
|
|
24
|
+
pixelCoord.y + callIndex * 0.5698402910,
|
|
25
|
+
s + callIndex * 0.6180339887
|
|
26
|
+
));
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
export { randomWGSL as default };
|
|
@@ -362,7 +362,7 @@ fn main(input: StrokeFragmentInput) -> @location(0) vec4<f32> {
|
|
|
362
362
|
discard;
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
|
-
var col = HOOK_getFinalColor(inputs.color);
|
|
365
|
+
var col = HOOK_getFinalColor(inputs.color, vec2<f32>(0.0, 0.0));
|
|
366
366
|
col = vec4<f32>(col.rgb, 1.0) * col.a;
|
|
367
367
|
HOOK_afterFragment();
|
|
368
368
|
return vec4<f32>(col);
|
|
@@ -416,9 +416,9 @@ fn main(input: FragmentInput) -> @location(0) vec4<f32> {
|
|
|
416
416
|
inputs.emissiveMaterial
|
|
417
417
|
);
|
|
418
418
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
419
|
+
var outColor = HOOK_getFinalColor(
|
|
420
|
+
HOOK_combineColors(components), input.vTexCoord
|
|
421
|
+
);
|
|
422
422
|
outColor = vec4<f32>(outColor.rgb * outColor.a, outColor.a);
|
|
423
423
|
HOOK_afterFragment();
|
|
424
424
|
return outColor;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import noiseWGSL from './shaders/functions/noise3DWGSL.js';
|
|
2
|
+
import randomWGSL from './shaders/functions/randomWGSL.js';
|
|
3
|
+
import randomVertWGSL from './shaders/functions/randomVertWGSL.js';
|
|
4
|
+
import randomComputeWGSL from './shaders/functions/randomComputeWGSL.js';
|
|
5
|
+
import { INSTANCE_ID_VARYING_NAME, BaseType, DataType, NodeTypeToName, NodeType, OpCode, OpCodeToSymbol, isStructType, StatementType, BlockType } from '../strands/ir_types.js';
|
|
2
6
|
import { getNodeDataFromID, extractNodeTypeInfo } from '../strands/ir_dag.js';
|
|
3
7
|
import { internalError } from '../strands/strands_FES.js';
|
|
4
|
-
import { v as variableNode, c as createStrandsNode, f as functionCallNode } from '../ir_builders-
|
|
8
|
+
import { v as variableNode, c as createStrandsNode, s as scalarLiteralNode, f as functionCallNode } from '../ir_builders-C2ebb6Lu.js';
|
|
5
9
|
import '../strands/ir_cfg.js';
|
|
6
10
|
import '../strands/strands_builtins.js';
|
|
7
11
|
|
|
@@ -206,10 +210,10 @@ const wgslBackend = {
|
|
|
206
210
|
// Add texture and sampler bindings for sampler2D uniforms to both vertex and fragment declarations
|
|
207
211
|
if (!strandsContext.renderer || !strandsContext.baseShader) return;
|
|
208
212
|
|
|
209
|
-
// Get the next available binding index from the renderer
|
|
210
213
|
let bindingIndex = strandsContext.renderer.getNextBindingIndex({
|
|
211
|
-
vert: strandsContext.baseShader.
|
|
212
|
-
frag: strandsContext.baseShader.
|
|
214
|
+
vert: strandsContext.baseShader._vertSrc,
|
|
215
|
+
frag: strandsContext.baseShader._fragSrc,
|
|
216
|
+
compute: strandsContext.baseShader._computeSrc,
|
|
213
217
|
});
|
|
214
218
|
|
|
215
219
|
for (const {name, typeInfo} of strandsContext.uniforms) {
|
|
@@ -226,6 +230,38 @@ const wgslBackend = {
|
|
|
226
230
|
}
|
|
227
231
|
}
|
|
228
232
|
},
|
|
233
|
+
addStorageBufferBindingsToDeclarations(strandsContext) {
|
|
234
|
+
if (!strandsContext.renderer || !strandsContext.baseShader) return;
|
|
235
|
+
|
|
236
|
+
const isComputeShader = strandsContext.baseShader.shaderType === 'compute';
|
|
237
|
+
let bindingIndex = strandsContext.renderer.getNextBindingIndex({
|
|
238
|
+
vert: strandsContext.baseShader._vertSrc,
|
|
239
|
+
frag: strandsContext.baseShader._fragSrc,
|
|
240
|
+
compute: strandsContext.baseShader._computeSrc,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
for (const {name, typeInfo} of strandsContext.uniforms) {
|
|
244
|
+
if (typeInfo.baseType === 'storage') {
|
|
245
|
+
const accessMode = isComputeShader ? 'read_write' : 'read';
|
|
246
|
+
let declaration;
|
|
247
|
+
if (typeInfo.schema) {
|
|
248
|
+
const structTypeName = `${name}Element`;
|
|
249
|
+
declaration = `struct ${structTypeName} ${typeInfo.schema.structBody}\n@group(0) @binding(${bindingIndex}) var<storage, ${accessMode}> ${name}: array<${structTypeName}>;`;
|
|
250
|
+
} else {
|
|
251
|
+
declaration = `@group(0) @binding(${bindingIndex}) var<storage, ${accessMode}> ${name}: array<f32>;`;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (isComputeShader) {
|
|
255
|
+
strandsContext.computeDeclarations.add(declaration);
|
|
256
|
+
} else {
|
|
257
|
+
strandsContext.vertexDeclarations.add(declaration);
|
|
258
|
+
strandsContext.fragmentDeclarations.add(declaration);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
bindingIndex += 1;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
},
|
|
229
265
|
getTypeName(baseType, dimension) {
|
|
230
266
|
const primitiveTypeName = TypeNames[baseType + dimension];
|
|
231
267
|
if (!primitiveTypeName) {
|
|
@@ -233,6 +269,19 @@ const wgslBackend = {
|
|
|
233
269
|
}
|
|
234
270
|
return primitiveTypeName;
|
|
235
271
|
},
|
|
272
|
+
getNoiseShaderSnippet() {
|
|
273
|
+
return noiseWGSL;
|
|
274
|
+
},
|
|
275
|
+
getRandomFragmentShaderSnippet() {
|
|
276
|
+
return randomWGSL;
|
|
277
|
+
},
|
|
278
|
+
getRandomVertexShaderSnippet() {
|
|
279
|
+
return randomVertWGSL;
|
|
280
|
+
},
|
|
281
|
+
getRandomComputeShaderSnippet() {
|
|
282
|
+
return randomComputeWGSL;
|
|
283
|
+
},
|
|
284
|
+
|
|
236
285
|
generateHookUniformKey(name, typeInfo) {
|
|
237
286
|
// For sampler2D types, we don't add them to the uniform struct,
|
|
238
287
|
// but we still need them in the shader's hooks object so that
|
|
@@ -240,6 +289,11 @@ const wgslBackend = {
|
|
|
240
289
|
if (typeInfo.baseType === 'sampler2D') {
|
|
241
290
|
return `${name}: sampler2D`; // Signal that this should not be added to uniform struct
|
|
242
291
|
}
|
|
292
|
+
// For storage buffers, we don't add them to the uniform struct
|
|
293
|
+
// Instead, they become separate storage buffer bindings
|
|
294
|
+
if (typeInfo.baseType === 'storage') {
|
|
295
|
+
return null; // Signal that this should not be added to uniform struct
|
|
296
|
+
}
|
|
243
297
|
return `${name}: ${this.getTypeName(typeInfo.baseType, typeInfo.dimension)}`;
|
|
244
298
|
},
|
|
245
299
|
generateVaryingVariable(varName, typeInfo) {
|
|
@@ -266,9 +320,13 @@ const wgslBackend = {
|
|
|
266
320
|
// Generate just a semicolon (unless suppressed)
|
|
267
321
|
generationContext.write(semicolon);
|
|
268
322
|
} else if (node.statementType === StatementType.EARLY_RETURN) {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
323
|
+
if (node.dependsOn && node.dependsOn.length > 0) {
|
|
324
|
+
const exprNodeID = node.dependsOn[0];
|
|
325
|
+
const expr = this.generateExpression(generationContext, dag, exprNodeID);
|
|
326
|
+
generationContext.write(`return ${expr}${semicolon}`);
|
|
327
|
+
} else {
|
|
328
|
+
generationContext.write(`return${semicolon}`);
|
|
329
|
+
}
|
|
272
330
|
}
|
|
273
331
|
},
|
|
274
332
|
generateAssignment(generationContext, dag, nodeID) {
|
|
@@ -280,6 +338,17 @@ const wgslBackend = {
|
|
|
280
338
|
const targetNode = getNodeDataFromID(dag, targetNodeID);
|
|
281
339
|
const semicolon = generationContext.suppressSemicolon ? '' : ';';
|
|
282
340
|
|
|
341
|
+
// Check if target is an array access (storage buffer assignment)
|
|
342
|
+
if (targetNode.opCode === OpCode.Binary.ARRAY_ACCESS) {
|
|
343
|
+
const [bufferID, indexID] = targetNode.dependsOn;
|
|
344
|
+
const bufferExpr = this.generateExpression(generationContext, dag, bufferID);
|
|
345
|
+
const indexExpr = this.generateExpression(generationContext, dag, indexID);
|
|
346
|
+
const sourceExpr = this.generateExpression(generationContext, dag, sourceNodeID);
|
|
347
|
+
const fieldSuffix = targetNode.identifier ? `.${targetNode.identifier}` : '';
|
|
348
|
+
generationContext.write(`${bufferExpr}[i32(${indexExpr})]${fieldSuffix} = ${sourceExpr}${semicolon}`);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
283
352
|
// Check if target is a swizzle assignment
|
|
284
353
|
if (targetNode.opCode === OpCode.Unary.SWIZZLE) {
|
|
285
354
|
const parentID = targetNode.dependsOn[0];
|
|
@@ -337,6 +406,10 @@ const wgslBackend = {
|
|
|
337
406
|
return `var ${tmp}: ${typeName} = ${expr};`;
|
|
338
407
|
},
|
|
339
408
|
generateReturnStatement(strandsContext, generationContext, rootNodeID, returnType) {
|
|
409
|
+
if (!returnType) {
|
|
410
|
+
generationContext.write('return;');
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
340
413
|
const dag = strandsContext.dag;
|
|
341
414
|
const rootNode = getNodeDataFromID(dag, rootNodeID);
|
|
342
415
|
if (isStructType(returnType)) {
|
|
@@ -377,9 +450,15 @@ const wgslBackend = {
|
|
|
377
450
|
}
|
|
378
451
|
}
|
|
379
452
|
|
|
380
|
-
//
|
|
453
|
+
// Detect instanceID usage in fragment context and rewrite to varying name
|
|
454
|
+
if (node.identifier === this.instanceIdReference() && generationContext.shaderContext === 'fragment') {
|
|
455
|
+
generationContext.strandsContext._instanceIDUsedInFragment = true;
|
|
456
|
+
return INSTANCE_ID_VARYING_NAME;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Check if this is a uniform variable (but not a texture or storage buffer)
|
|
381
460
|
const uniform = generationContext.strandsContext?.uniforms?.find(uniform => uniform.name === node.identifier);
|
|
382
|
-
if (uniform && uniform.typeInfo.baseType !== 'sampler2D') {
|
|
461
|
+
if (uniform && uniform.typeInfo.baseType !== 'sampler2D' && uniform.typeInfo.baseType !== 'storage') {
|
|
383
462
|
return `hooks.${node.identifier}`;
|
|
384
463
|
}
|
|
385
464
|
|
|
@@ -398,6 +477,13 @@ const wgslBackend = {
|
|
|
398
477
|
const deps = node.dependsOn.map((dep) => this.generateExpression(generationContext, dag, dep));
|
|
399
478
|
return `${T}(${deps.join(', ')})`;
|
|
400
479
|
}
|
|
480
|
+
if (node.opCode === OpCode.Nary.TERNARY) {
|
|
481
|
+
const [condID, trueID, falseID] = node.dependsOn;
|
|
482
|
+
const cond = this.generateExpression(generationContext, dag, condID);
|
|
483
|
+
const trueExpr = this.generateExpression(generationContext, dag, trueID);
|
|
484
|
+
const falseExpr = this.generateExpression(generationContext, dag, falseID);
|
|
485
|
+
return `select(${falseExpr}, ${trueExpr}, ${cond})`;
|
|
486
|
+
}
|
|
401
487
|
if (node.opCode === OpCode.Nary.FUNCTION_CALL) {
|
|
402
488
|
// Convert mod() function calls to % operator in WGSL
|
|
403
489
|
if (node.identifier === 'mod' && node.dependsOn.length === 2) {
|
|
@@ -419,6 +505,18 @@ const wgslBackend = {
|
|
|
419
505
|
}
|
|
420
506
|
|
|
421
507
|
const functionArgs = node.dependsOn.map(arg =>this.generateExpression(generationContext, dag, arg));
|
|
508
|
+
|
|
509
|
+
if (node.identifier === 'random') {
|
|
510
|
+
const ctx = generationContext.shaderContext;
|
|
511
|
+
if (ctx === 'fragment') {
|
|
512
|
+
functionArgs.push('_p5FragPos.xy');
|
|
513
|
+
} else if (ctx === 'vertex') {
|
|
514
|
+
functionArgs.push('f32(_p5VertexId)');
|
|
515
|
+
} else if (ctx === 'compute') {
|
|
516
|
+
functionArgs.push('_p5GlobalId');
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
422
520
|
return `${node.identifier}(${functionArgs.join(', ')})`;
|
|
423
521
|
}
|
|
424
522
|
if (node.opCode === OpCode.Binary.MEMBER_ACCESS) {
|
|
@@ -432,6 +530,13 @@ const wgslBackend = {
|
|
|
432
530
|
const parentExpr = this.generateExpression(generationContext, dag, parentID);
|
|
433
531
|
return `${parentExpr}.${node.swizzle}`;
|
|
434
532
|
}
|
|
533
|
+
if (node.opCode === OpCode.Binary.ARRAY_ACCESS) {
|
|
534
|
+
const [bufferID, indexID] = node.dependsOn;
|
|
535
|
+
const bufferExpr = this.generateExpression(generationContext, dag, bufferID);
|
|
536
|
+
const indexExpr = this.generateExpression(generationContext, dag, indexID);
|
|
537
|
+
const fieldSuffix = node.identifier ? `.${node.identifier}` : '';
|
|
538
|
+
return `${bufferExpr}[i32(${indexExpr})]${fieldSuffix}`;
|
|
539
|
+
}
|
|
435
540
|
if (node.dependsOn.length === 2) {
|
|
436
541
|
const [lID, rID] = node.dependsOn;
|
|
437
542
|
const left = this.generateExpression(generationContext, dag, lID);
|
|
@@ -505,12 +610,25 @@ const wgslBackend = {
|
|
|
505
610
|
const samplerVariable = variableNode(strandsContext, { baseType: BaseType.SAMPLER, dimension: 1 }, samplerIdentifier);
|
|
506
611
|
const samplerNode = createStrandsNode(samplerVariable.id, samplerVariable.dimension, strandsContext);
|
|
507
612
|
|
|
508
|
-
// Create
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
613
|
+
// Create a LOD literal node (0.0) so we can use textureSampleLevel instead
|
|
614
|
+
// of textureSample. textureSample doesn't let you use uniform values in control
|
|
615
|
+
// flow, whereas textureSampleLevel does. While we don't have mipmaps, we don't
|
|
616
|
+
// miss out.
|
|
617
|
+
// TODO: if we *do* add mipmap support, update this logic -- we'd need to hoist
|
|
618
|
+
// the texture lookup out of the control flow.
|
|
619
|
+
const lodLiteral = scalarLiteralNode(
|
|
620
|
+
strandsContext,
|
|
621
|
+
{ dimension: 1, baseType: BaseType.FLOAT },
|
|
622
|
+
0.0
|
|
623
|
+
);
|
|
624
|
+
const lodNode = createStrandsNode(lodLiteral.id, lodLiteral.dimension, strandsContext);
|
|
625
|
+
|
|
626
|
+
// Create the augmented args: [texture, sampler, coords, lod]
|
|
627
|
+
const augmentedArgs = [textureArg, samplerNode, coordsArg, lodNode];
|
|
628
|
+
|
|
629
|
+
const { id, dimension } = functionCallNode(strandsContext, 'textureSampleLevel', augmentedArgs, {
|
|
512
630
|
overloads: [{
|
|
513
|
-
params: [DataType.sampler2D, DataType.sampler, DataType.float2],
|
|
631
|
+
params: [DataType.sampler2D, DataType.sampler, DataType.float2, DataType.float1],
|
|
514
632
|
returnType: DataType.float4
|
|
515
633
|
}]
|
|
516
634
|
});
|
|
@@ -520,6 +638,10 @@ const wgslBackend = {
|
|
|
520
638
|
instanceIdReference() {
|
|
521
639
|
return 'instanceID';
|
|
522
640
|
},
|
|
641
|
+
|
|
642
|
+
generateInstanceIDVarying() {
|
|
643
|
+
return { name: INSTANCE_ID_VARYING_NAME, declaration: `${INSTANCE_ID_VARYING_NAME}: i32`, source: 'i32(instanceID)', interpolation: 'flat' };
|
|
644
|
+
},
|
|
523
645
|
};
|
|
524
646
|
|
|
525
647
|
export { wgslBackend };
|