@triforge/shader-core 0.1.1 → 0.2.0
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/bundle.js +81 -28
- package/dist/core/CompileContext.d.ts.map +1 -1
- package/dist/core/CompileContext.js +50 -28
- package/dist/core/glslIdentifier.d.ts +17 -0
- package/dist/core/glslIdentifier.d.ts.map +1 -0
- package/dist/core/glslIdentifier.js +37 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/nodes/input/Attribute.d.ts +1 -1
- package/dist/nodes/input/Attribute.d.ts.map +1 -1
- package/dist/nodes/input/Attribute.js +8 -1
- package/dist/nodes/input/CameraData.d.ts +1 -1
- package/dist/nodes/input/ColorAttribute.d.ts +1 -1
- package/dist/nodes/input/Geometry.d.ts +1 -1
- package/dist/nodes/input/HairInfo.d.ts +1 -1
- package/dist/nodes/input/LayerWeight.d.ts +1 -1
- package/dist/nodes/input/LightPath.d.ts +1 -1
- package/dist/nodes/input/ObjectInfo.d.ts +1 -1
- package/dist/nodes/input/OceanAttribute.d.ts +1 -1
- package/dist/nodes/input/ParticleInfo.d.ts +1 -1
- package/dist/nodes/input/RGB.d.ts +1 -1
- package/dist/nodes/input/ScreenCamera.d.ts +1 -1
- package/dist/nodes/input/Tangent.d.ts +1 -1
- package/dist/nodes/input/TextureCoordinate.d.ts +1 -1
- package/dist/nodes/input/UVMap.d.ts +1 -1
- package/dist/nodes/input/Value.d.ts +1 -1
- package/dist/nodes/input/Wireframe.d.ts +1 -1
- package/dist/nodes/output/MaterialOutput.d.ts +1 -1
- package/dist/nodes/output/ScreenOutput.d.ts +1 -1
- package/dist/nodes/process/AddShader.d.ts +1 -1
- package/dist/nodes/process/AnimatedNoiseTexture.d.ts +1 -1
- package/dist/nodes/process/Blackbody.d.ts +1 -1
- package/dist/nodes/process/BrickTexture.d.ts +1 -1
- package/dist/nodes/process/BrightContrast.d.ts +1 -1
- package/dist/nodes/process/Bump.d.ts +1 -1
- package/dist/nodes/process/CheckerTexture.d.ts +1 -1
- package/dist/nodes/process/Clamp.d.ts +1 -1
- package/dist/nodes/process/ColorRamp.d.ts +1 -1
- package/dist/nodes/process/CombineColor.d.ts +1 -1
- package/dist/nodes/process/CombineRGB.d.ts +1 -1
- package/dist/nodes/process/CombineXYZ.d.ts +1 -1
- package/dist/nodes/process/DiffuseBSDF.d.ts +1 -1
- package/dist/nodes/process/Emission.d.ts +1 -1
- package/dist/nodes/process/EnvironmentTexture.d.ts +1 -1
- package/dist/nodes/process/EnvironmentTexture.d.ts.map +1 -1
- package/dist/nodes/process/EnvironmentTexture.js +2 -0
- package/dist/nodes/process/FloatCurve.d.ts +1 -1
- package/dist/nodes/process/Fresnel.d.ts +1 -1
- package/dist/nodes/process/Gamma.d.ts +1 -1
- package/dist/nodes/process/GlassBSDF.d.ts +1 -1
- package/dist/nodes/process/GlossyBSDF.d.ts +1 -1
- package/dist/nodes/process/GradientTexture.d.ts +1 -1
- package/dist/nodes/process/HashValue.d.ts +1 -1
- package/dist/nodes/process/HueSaturationValue.d.ts +1 -1
- package/dist/nodes/process/ImageTexture.d.ts +1 -1
- package/dist/nodes/process/ImageTexture.d.ts.map +1 -1
- package/dist/nodes/process/ImageTexture.js +3 -1
- package/dist/nodes/process/InvertColor.d.ts +1 -1
- package/dist/nodes/process/MagicTexture.d.ts +1 -1
- package/dist/nodes/process/MapRange.d.ts +1 -1
- package/dist/nodes/process/Mapping.d.ts +1 -4
- package/dist/nodes/process/Mapping.d.ts.map +1 -1
- package/dist/nodes/process/Mapping.js +28 -25
- package/dist/nodes/process/Math.d.ts +1 -1
- package/dist/nodes/process/MixRGB.d.ts +1 -1
- package/dist/nodes/process/MixShader.d.ts +1 -1
- package/dist/nodes/process/MusgraveTexture.d.ts +1 -1
- package/dist/nodes/process/NoiseTexture.d.ts +1 -1
- package/dist/nodes/process/Normal.d.ts +1 -1
- package/dist/nodes/process/NormalMap.d.ts +12 -8
- package/dist/nodes/process/NormalMap.d.ts.map +1 -1
- package/dist/nodes/process/NormalMap.js +34 -21
- package/dist/nodes/process/PrincipledBSDF.d.ts +1 -1
- package/dist/nodes/process/PrincipledHair.d.ts +1 -1
- package/dist/nodes/process/PrincipledVolume.d.ts +1 -1
- package/dist/nodes/process/RGBCurves.d.ts +1 -1
- package/dist/nodes/process/RGBtoBW.d.ts +1 -1
- package/dist/nodes/process/RefractionBSDF.d.ts +1 -1
- package/dist/nodes/process/SchwarzschildMarch.d.ts +1 -1
- package/dist/nodes/process/SeparateColor.d.ts +1 -1
- package/dist/nodes/process/SeparateRGB.d.ts +1 -1
- package/dist/nodes/process/SeparateXYZ.d.ts +1 -1
- package/dist/nodes/process/ShaderScript.d.ts +1 -1
- package/dist/nodes/process/ShaderScript.d.ts.map +1 -1
- package/dist/nodes/process/ShaderScript.js +5 -0
- package/dist/nodes/process/ShaderToRGB.d.ts +1 -1
- package/dist/nodes/process/SheenBSDF.d.ts +1 -1
- package/dist/nodes/process/SpecularBSDF.d.ts +1 -1
- package/dist/nodes/process/SubsurfaceScattering.d.ts +1 -1
- package/dist/nodes/process/ToonBSDF.d.ts +1 -1
- package/dist/nodes/process/TranslucentBSDF.d.ts +1 -1
- package/dist/nodes/process/VectorCurves.d.ts +1 -1
- package/dist/nodes/process/VectorMath.d.ts +1 -1
- package/dist/nodes/process/VectorRotate.d.ts +1 -1
- package/dist/nodes/process/VectorTransform.d.ts +1 -1
- package/dist/nodes/process/VolumeAbsorption.d.ts +1 -1
- package/dist/nodes/process/VolumeScatter.d.ts +1 -1
- package/dist/nodes/process/VoronoiTexture.d.ts +1 -1
- package/dist/nodes/process/WaveTexture.d.ts +1 -1
- package/dist/nodes/process/Wavelength.d.ts +1 -1
- package/dist/nodes/process/WhiteNoise.d.ts +1 -1
- package/package.json +50 -50
package/dist/bundle.js
CHANGED
|
@@ -247,6 +247,24 @@ var InputNode = class extends ShaderNode {
|
|
|
247
247
|
}
|
|
248
248
|
};
|
|
249
249
|
|
|
250
|
+
// src/core/glslIdentifier.ts
|
|
251
|
+
var GLSL_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
252
|
+
function isValidGlslIdentifier(name) {
|
|
253
|
+
if (typeof name !== "string") return false;
|
|
254
|
+
if (!GLSL_IDENTIFIER.test(name)) return false;
|
|
255
|
+
if (name.startsWith("gl_")) return false;
|
|
256
|
+
if (name.includes("__")) return false;
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
function assertGlslIdentifier(name, context) {
|
|
260
|
+
if (!isValidGlslIdentifier(name)) {
|
|
261
|
+
throw new Error(
|
|
262
|
+
`[st-shader-core] ${context}: "${String(name)}" is not a valid GLSL identifier. Only letters, digits and single underscores are allowed (must start with a letter or underscore, may not start with "gl_" or contain "__"). This guards against GLSL injection.`
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
return name;
|
|
266
|
+
}
|
|
267
|
+
|
|
250
268
|
// src/core/CompileContext.ts
|
|
251
269
|
var CompileContext = class _CompileContext {
|
|
252
270
|
constructor() {
|
|
@@ -290,7 +308,14 @@ var CompileContext = class _CompileContext {
|
|
|
290
308
|
*/
|
|
291
309
|
resolveInput(socket) {
|
|
292
310
|
if (socket.connection) {
|
|
293
|
-
|
|
311
|
+
const varName = this.outputVar(socket.connection.node, socket.connection.name);
|
|
312
|
+
if (socket.type === "vector" && socket.connection.type !== "vector") {
|
|
313
|
+
return `(${varName}).xy`;
|
|
314
|
+
}
|
|
315
|
+
if (socket.type === "color" && socket.connection.type === "vector") {
|
|
316
|
+
return `vec3(${varName}, 0.0)`;
|
|
317
|
+
}
|
|
318
|
+
return varName;
|
|
294
319
|
}
|
|
295
320
|
if (socket.uniformName !== null) {
|
|
296
321
|
if (!(socket.uniformName in this._uniforms)) {
|
|
@@ -337,6 +362,8 @@ var CompileContext = class _CompileContext {
|
|
|
337
362
|
const call = node.compileCall(this).trim();
|
|
338
363
|
if (call) this.calls.push(call);
|
|
339
364
|
for (const inj of node.vertexInjections()) {
|
|
365
|
+
assertGlslIdentifier(inj.attrName, `${node.nodeType} vertex attribute name`);
|
|
366
|
+
assertGlslIdentifier(inj.varyingName, `${node.nodeType} varying name`);
|
|
340
367
|
if (!this._vertexInjections.has(inj.varyingName)) {
|
|
341
368
|
this._vertexInjections.set(inj.varyingName, { attrName: inj.attrName, attrType: inj.attrType });
|
|
342
369
|
}
|
|
@@ -401,6 +428,8 @@ var CompileContext = class _CompileContext {
|
|
|
401
428
|
typesCompatible(from, to) {
|
|
402
429
|
if (from === to) return true;
|
|
403
430
|
if ((from === "shader" || from === "color") && (to === "shader" || to === "color")) return true;
|
|
431
|
+
if ((from === "color" || from === "shader") && to === "vector") return true;
|
|
432
|
+
if (from === "vector" && to === "color") return true;
|
|
404
433
|
return false;
|
|
405
434
|
}
|
|
406
435
|
// ── GLSL builders ─────────────────────────────────────────────────
|
|
@@ -784,6 +813,7 @@ var Attribute = class extends InputNode {
|
|
|
784
813
|
super("Attribute");
|
|
785
814
|
/** 0 = vec3, 1 = float. Stored as number for keyframe/GSAP compat. */
|
|
786
815
|
this.parameters = { attributeType: 0 };
|
|
816
|
+
assertGlslIdentifier(attributeName, "Attribute name");
|
|
787
817
|
this._safeAttrName = attributeName.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
788
818
|
this.attributeName = attributeName;
|
|
789
819
|
this.parameters.attributeType = attributeType === "float" ? 1 : 0;
|
|
@@ -1997,6 +2027,7 @@ var ImageTexture = class extends ProcessNode {
|
|
|
1997
2027
|
fix: 'new ImageTexture({ uniformName: "uMyTexture" })\n After compile(): mat.material.uniforms.uMyTexture = { value: texture }'
|
|
1998
2028
|
});
|
|
1999
2029
|
}
|
|
2030
|
+
assertGlslIdentifier(inputs.uniformName, "ImageTexture uniformName");
|
|
2000
2031
|
this.uniformName = inputs.uniformName;
|
|
2001
2032
|
this._inputs = this.createInputs(inputs, { vector: ["vector", null] });
|
|
2002
2033
|
this._outputs = this.createOutputs({ Color: "color", Alpha: "float" });
|
|
@@ -2011,7 +2042,7 @@ var ImageTexture = class extends ProcessNode {
|
|
|
2011
2042
|
return `uniform sampler2D ${this.uniformName};`;
|
|
2012
2043
|
}
|
|
2013
2044
|
compileCall(ctx) {
|
|
2014
|
-
const uv = this._inputs.vector.isConnected() ? ctx.
|
|
2045
|
+
const uv = this._inputs.vector.isConnected() ? ctx.resolveInput(this._inputs.vector) : "vUv";
|
|
2015
2046
|
const cv = ctx.outputVar(this, "Color");
|
|
2016
2047
|
const av = ctx.outputVar(this, "Alpha");
|
|
2017
2048
|
return [
|
|
@@ -2043,6 +2074,7 @@ var EnvironmentTexture = class extends ProcessNode {
|
|
|
2043
2074
|
fix: 'new EnvironmentTexture({ uniformName: "uEnv" })\n After compile(): mat.material.uniforms.uEnv = { value: cubeTexture }'
|
|
2044
2075
|
});
|
|
2045
2076
|
}
|
|
2077
|
+
assertGlslIdentifier(inputs.uniformName, "EnvironmentTexture uniformName");
|
|
2046
2078
|
this._uniformName = inputs.uniformName;
|
|
2047
2079
|
this._inputs = this.createInputs(inputs, {
|
|
2048
2080
|
vector: ["color", null],
|
|
@@ -2621,7 +2653,7 @@ vec3 _st_wavelength(float w) {
|
|
|
2621
2653
|
};
|
|
2622
2654
|
|
|
2623
2655
|
// src/nodes/process/NormalMap.ts
|
|
2624
|
-
var NormalMap = class extends ProcessNode {
|
|
2656
|
+
var NormalMap = class _NormalMap extends ProcessNode {
|
|
2625
2657
|
get nodeType() {
|
|
2626
2658
|
return "NormalMap";
|
|
2627
2659
|
}
|
|
@@ -2634,19 +2666,35 @@ var NormalMap = class extends ProcessNode {
|
|
|
2634
2666
|
category: "Vector",
|
|
2635
2667
|
color: "#4a3a8a",
|
|
2636
2668
|
cost: "medium",
|
|
2637
|
-
costNote: "
|
|
2669
|
+
costNote: "Builds a derivative-based TBN frame per fragment."
|
|
2638
2670
|
};
|
|
2639
2671
|
}
|
|
2640
2672
|
static {
|
|
2641
2673
|
this.glslFunction = `
|
|
2642
|
-
vec3 _st_normalMap(
|
|
2643
|
-
|
|
2674
|
+
vec3 _st_normalMap(vec3 sampledColor, float strength, vec3 N, vec3 P, vec2 uv) {
|
|
2675
|
+
vec3 n = sampledColor * 2.0 - 1.0;
|
|
2676
|
+
n.xy *= strength;
|
|
2677
|
+
|
|
2678
|
+
// Derivative-based cotangent frame (Sch\xFCler) \u2014 no vertex tangent attribute needed.
|
|
2679
|
+
vec3 dp1 = dFdx(P);
|
|
2680
|
+
vec3 dp2 = dFdy(P);
|
|
2681
|
+
vec2 duv1 = dFdx(uv);
|
|
2682
|
+
vec2 duv2 = dFdy(uv);
|
|
2683
|
+
|
|
2684
|
+
vec3 dp2perp = cross(dp2, N);
|
|
2685
|
+
vec3 dp1perp = cross(N, dp1);
|
|
2686
|
+
vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
|
|
2687
|
+
vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
|
|
2688
|
+
|
|
2689
|
+
float invmax = inversesqrt(max(dot(T, T), dot(B, B)));
|
|
2690
|
+
mat3 TBN = mat3(T * invmax, B * invmax, N);
|
|
2691
|
+
return normalize(TBN * n);
|
|
2644
2692
|
}`;
|
|
2645
2693
|
}
|
|
2646
2694
|
constructor(inputs = {}) {
|
|
2647
2695
|
super("NormalMap");
|
|
2648
2696
|
this._inputs = this.createInputs(inputs, {
|
|
2649
|
-
|
|
2697
|
+
color: ["color", [0.5, 0.5, 1]],
|
|
2650
2698
|
strength: ["float", inputs.strength ?? 1]
|
|
2651
2699
|
});
|
|
2652
2700
|
this._outputs = this.createOutputs({ Normal: "color" });
|
|
@@ -2658,17 +2706,13 @@ vec3 _st_normalMap(float fac, float strength) {
|
|
|
2658
2706
|
return this._outputs;
|
|
2659
2707
|
}
|
|
2660
2708
|
compileDefs() {
|
|
2661
|
-
return
|
|
2709
|
+
return _NormalMap.glslFunction;
|
|
2662
2710
|
}
|
|
2663
2711
|
compileCall(ctx) {
|
|
2664
|
-
const
|
|
2712
|
+
const color = ctx.resolveInput(this._inputs.color);
|
|
2665
2713
|
const strength = ctx.resolveInput(this._inputs.strength);
|
|
2666
2714
|
const normalVar = ctx.outputVar(this, "Normal");
|
|
2667
|
-
return
|
|
2668
|
-
`float _nm_nx_${this.id} = dFdx(${facVar});`,
|
|
2669
|
-
`float _nm_ny_${this.id} = dFdy(${facVar});`,
|
|
2670
|
-
`vec3 ${normalVar} = normalize(vec3(-_nm_nx_${this.id} * ${strength}, 1.0, -_nm_ny_${this.id} * ${strength}));`
|
|
2671
|
-
].join("\n ");
|
|
2715
|
+
return `vec3 ${normalVar} = _st_normalMap(${color}, ${strength}, normalize(vNormal), vPosition, vUv);`;
|
|
2672
2716
|
}
|
|
2673
2717
|
};
|
|
2674
2718
|
|
|
@@ -2770,10 +2814,12 @@ vec3 _st_rotateZ(vec3 v, float a) {
|
|
|
2770
2814
|
constructor(inputs = {}) {
|
|
2771
2815
|
super("Mapping");
|
|
2772
2816
|
this.mode = inputs.mode ?? "TEXTURE";
|
|
2773
|
-
this.
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2817
|
+
this._inputs = this.createInputs(inputs, {
|
|
2818
|
+
vector: ["color", null],
|
|
2819
|
+
location: ["color", inputs.location ?? [0, 0, 0]],
|
|
2820
|
+
rotation: ["color", inputs.rotation ?? [0, 0, 0]],
|
|
2821
|
+
scale: ["color", inputs.scale ?? [1, 1, 1]]
|
|
2822
|
+
});
|
|
2777
2823
|
this._outputs = this.createOutputs({ Vector: "color" });
|
|
2778
2824
|
}
|
|
2779
2825
|
getInputSockets() {
|
|
@@ -2787,18 +2833,19 @@ vec3 _st_rotateZ(vec3 v, float a) {
|
|
|
2787
2833
|
}
|
|
2788
2834
|
compileCall(ctx) {
|
|
2789
2835
|
const v = ctx.resolveInput(this._inputs.vector);
|
|
2836
|
+
const loc = ctx.resolveInput(this._inputs.location);
|
|
2837
|
+
const rot = ctx.resolveInput(this._inputs.rotation);
|
|
2838
|
+
const scl = ctx.resolveInput(this._inputs.scale);
|
|
2790
2839
|
const out = ctx.outputVar(this, "Vector");
|
|
2791
|
-
const toRad = (
|
|
2792
|
-
const [lx, ly, lz] = this.loc;
|
|
2793
|
-
const [rx, ry, rz] = this.rot.map(Number);
|
|
2794
|
-
const [sx, sy, sz] = this.scl;
|
|
2840
|
+
const toRad = (Math.PI / 180).toFixed(6);
|
|
2795
2841
|
return [
|
|
2796
2842
|
`vec3 _mp_v_${this.id} = ${v};`,
|
|
2797
|
-
`
|
|
2798
|
-
`_mp_v_${this.id} =
|
|
2799
|
-
`_mp_v_${this.id} =
|
|
2800
|
-
`_mp_v_${this.id} =
|
|
2801
|
-
`_mp_v_${this.id} = _mp_v_${this.id}
|
|
2843
|
+
`vec3 _mp_r_${this.id} = ${rot} * ${toRad};`,
|
|
2844
|
+
`_mp_v_${this.id} = _mp_v_${this.id} - ${loc};`,
|
|
2845
|
+
`_mp_v_${this.id} = _st_rotateX(_mp_v_${this.id}, _mp_r_${this.id}.x);`,
|
|
2846
|
+
`_mp_v_${this.id} = _st_rotateY(_mp_v_${this.id}, _mp_r_${this.id}.y);`,
|
|
2847
|
+
`_mp_v_${this.id} = _st_rotateZ(_mp_v_${this.id}, _mp_r_${this.id}.z);`,
|
|
2848
|
+
`_mp_v_${this.id} = _mp_v_${this.id} * ${scl};`,
|
|
2802
2849
|
`vec3 ${out} = _mp_v_${this.id};`
|
|
2803
2850
|
].join("\n ");
|
|
2804
2851
|
}
|
|
@@ -4836,6 +4883,7 @@ var ShaderScript = class extends ProcessNode {
|
|
|
4836
4883
|
const defs = {};
|
|
4837
4884
|
const supplied = {};
|
|
4838
4885
|
for (const [name, spec] of Object.entries(config.inputs ?? {})) {
|
|
4886
|
+
assertGlslIdentifier(name, "ShaderScript input name");
|
|
4839
4887
|
if (Array.isArray(spec)) {
|
|
4840
4888
|
const [type, defaultVal] = spec;
|
|
4841
4889
|
defs[name] = [type, defaultVal];
|
|
@@ -4845,6 +4893,9 @@ var ShaderScript = class extends ProcessNode {
|
|
|
4845
4893
|
supplied[name] = sock;
|
|
4846
4894
|
}
|
|
4847
4895
|
}
|
|
4896
|
+
for (const name of Object.keys(this._outputDecl)) {
|
|
4897
|
+
assertGlslIdentifier(name, "ShaderScript output name");
|
|
4898
|
+
}
|
|
4848
4899
|
this._inputs = this.createInputs(supplied, defs);
|
|
4849
4900
|
this._outputs = this.createOutputs(this._outputDecl);
|
|
4850
4901
|
}
|
|
@@ -5574,5 +5625,7 @@ export {
|
|
|
5574
5625
|
WaveTexture,
|
|
5575
5626
|
Wavelength,
|
|
5576
5627
|
WhiteNoise,
|
|
5577
|
-
Wireframe
|
|
5628
|
+
Wireframe,
|
|
5629
|
+
assertGlslIdentifier,
|
|
5630
|
+
isValidGlslIdentifier
|
|
5578
5631
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CompileContext.d.ts","sourceRoot":"","sources":["../../src/core/CompileContext.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CompileContext.d.ts","sourceRoot":"","sources":["../../src/core/CompileContext.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAI,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAQ,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IAClD,KAAK,EAAW,UAAU,EAAE,CAAA;CAC7B;AAED;;;;;;;;;GASG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAqD;IACpE,OAAO,CAAC,QAAQ,CAAoD;IACpE,OAAO,CAAC,KAAK,CAAgD;IAC7D,OAAO,CAAC,WAAW,CAAiD;IACpE,OAAO,CAAC,IAAI,CAAiD;IAC7D,OAAO,CAAC,KAAK,CAAgD;IAC7D,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,SAAS,CAAuD;IACxE,0FAA0F;IAC1F,OAAO,CAAC,iBAAiB,CAAiE;IAI1F,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB;IAcjD;;;OAGG;IACH,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAKvD;;;;;OAKG;IACH,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,MAAM;IAgClD,OAAO,CAAC,KAAK;IA8Bb,OAAO,CAAC,IAAI;IAyBZ,OAAO,CAAC,QAAQ;IA0BhB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,YAAY;IAsCpB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,iBAAiB;IAuBzB,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,SAAS;IAqBjB,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAS3D,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAQrC,OAAO,CAAC,SAAS;CAGlB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ShaderNodeError } from './ShaderNodeError.js';
|
|
2
2
|
import { ShaderConfig } from './ShaderConfig.js';
|
|
3
|
+
import { assertGlslIdentifier } from './glslIdentifier.js';
|
|
3
4
|
/**
|
|
4
5
|
* Walks the node graph from an OutputNode, validates all connections,
|
|
5
6
|
* deduplicates GLSL function definitions, scopes variable names to node IDs,
|
|
@@ -52,7 +53,16 @@ export class CompileContext {
|
|
|
52
53
|
*/
|
|
53
54
|
resolveInput(socket) {
|
|
54
55
|
if (socket.connection) {
|
|
55
|
-
|
|
56
|
+
const varName = this.outputVar(socket.connection.node, socket.connection.name);
|
|
57
|
+
// vec3 (color/shader) → vec2 (vector) implicit conversion, e.g. Mapping.Vector → ImageTexture.vector
|
|
58
|
+
if (socket.type === 'vector' && socket.connection.type !== 'vector') {
|
|
59
|
+
return `(${varName}).xy`;
|
|
60
|
+
}
|
|
61
|
+
// vec2 (vector) → vec3 (color) implicit conversion, e.g. TextureCoordinate.UV → Mapping.vector
|
|
62
|
+
if (socket.type === 'color' && socket.connection.type === 'vector') {
|
|
63
|
+
return `vec3(${varName}, 0.0)`;
|
|
64
|
+
}
|
|
65
|
+
return varName;
|
|
56
66
|
}
|
|
57
67
|
if (socket.uniformName !== null) {
|
|
58
68
|
if (!(socket.uniformName in this._uniforms)) {
|
|
@@ -103,8 +113,13 @@ export class CompileContext {
|
|
|
103
113
|
const call = node.compileCall(this).trim();
|
|
104
114
|
if (call)
|
|
105
115
|
this.calls.push(call);
|
|
106
|
-
// Collect vertex attribute injections from this node
|
|
116
|
+
// Collect vertex attribute injections from this node. Both the attribute
|
|
117
|
+
// name and the varying name are emitted verbatim into GLSL source, so
|
|
118
|
+
// both must be validated here — this is the single chokepoint covering
|
|
119
|
+
// every current and future vertexInjections() implementor.
|
|
107
120
|
for (const inj of node.vertexInjections()) {
|
|
121
|
+
assertGlslIdentifier(inj.attrName, `${node.nodeType} vertex attribute name`);
|
|
122
|
+
assertGlslIdentifier(inj.varyingName, `${node.nodeType} varying name`);
|
|
108
123
|
if (!this._vertexInjections.has(inj.varyingName)) {
|
|
109
124
|
this._vertexInjections.set(inj.varyingName, { attrName: inj.attrName, attrType: inj.attrType });
|
|
110
125
|
}
|
|
@@ -186,6 +201,13 @@ export class CompileContext {
|
|
|
186
201
|
// shader and color are both vec3 — compatible
|
|
187
202
|
if ((from === 'shader' || from === 'color') && (to === 'shader' || to === 'color'))
|
|
188
203
|
return true;
|
|
204
|
+
// vec3 (color/shader) implicitly narrows to vec2 (vector) via .xy, mirroring Blender's
|
|
205
|
+
// Mapping (vector output) → Image Texture Vector panning graph
|
|
206
|
+
if ((from === 'color' || from === 'shader') && to === 'vector')
|
|
207
|
+
return true;
|
|
208
|
+
// vec2 (vector) implicitly widens to vec3 (color), e.g. Texture Coordinate UV → Mapping.vector
|
|
209
|
+
if (from === 'vector' && to === 'color')
|
|
210
|
+
return true;
|
|
189
211
|
return false;
|
|
190
212
|
}
|
|
191
213
|
// ── GLSL builders ─────────────────────────────────────────────────
|
|
@@ -196,18 +218,18 @@ export class CompileContext {
|
|
|
196
218
|
const customAssigns = [...this._vertexInjections.entries()]
|
|
197
219
|
.map(([vName, { attrName }]) => ` ${vName} = ${attrName};`)
|
|
198
220
|
.join('\n');
|
|
199
|
-
return `
|
|
200
|
-
varying vec2 vUv;
|
|
201
|
-
varying vec3 vNormal;
|
|
202
|
-
varying vec3 vPosition;
|
|
203
|
-
${customAttrs}
|
|
204
|
-
|
|
205
|
-
void main() {
|
|
206
|
-
vUv = uv;
|
|
207
|
-
vNormal = normalize(mat3(transpose(inverse(modelMatrix))) * normal);
|
|
208
|
-
vPosition = (modelMatrix * vec4(position, 1.0)).xyz;
|
|
209
|
-
${customAssigns}
|
|
210
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
221
|
+
return `
|
|
222
|
+
varying vec2 vUv;
|
|
223
|
+
varying vec3 vNormal;
|
|
224
|
+
varying vec3 vPosition;
|
|
225
|
+
${customAttrs}
|
|
226
|
+
|
|
227
|
+
void main() {
|
|
228
|
+
vUv = uv;
|
|
229
|
+
vNormal = normalize(mat3(transpose(inverse(modelMatrix))) * normal);
|
|
230
|
+
vPosition = (modelMatrix * vec4(position, 1.0)).xyz;
|
|
231
|
+
${customAssigns}
|
|
232
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
211
233
|
}`.trim();
|
|
212
234
|
}
|
|
213
235
|
buildUniformDeclarations() {
|
|
@@ -222,20 +244,20 @@ ${customAssigns}
|
|
|
222
244
|
.join('\n');
|
|
223
245
|
const defsBlock = this.defs.join('\n\n');
|
|
224
246
|
const callsBlock = this.calls.map(c => ` ${c}`).join('\n');
|
|
225
|
-
return `
|
|
226
|
-
precision mediump float;
|
|
227
|
-
|
|
228
|
-
varying vec2 vUv;
|
|
229
|
-
varying vec3 vNormal;
|
|
230
|
-
varying vec3 vPosition;
|
|
231
|
-
${customVaryings}
|
|
232
|
-
|
|
233
|
-
${uniformsBlock}
|
|
234
|
-
|
|
235
|
-
${defsBlock}
|
|
236
|
-
|
|
237
|
-
void main() {
|
|
238
|
-
${callsBlock}
|
|
247
|
+
return `
|
|
248
|
+
precision mediump float;
|
|
249
|
+
|
|
250
|
+
varying vec2 vUv;
|
|
251
|
+
varying vec3 vNormal;
|
|
252
|
+
varying vec3 vPosition;
|
|
253
|
+
${customVaryings}
|
|
254
|
+
|
|
255
|
+
${uniformsBlock}
|
|
256
|
+
|
|
257
|
+
${defsBlock}
|
|
258
|
+
|
|
259
|
+
void main() {
|
|
260
|
+
${callsBlock}
|
|
239
261
|
}`.trim();
|
|
240
262
|
}
|
|
241
263
|
// ── Literal conversion ────────────────────────────────────────────
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GLSL identifier validation — the single security boundary for any string
|
|
3
|
+
* that a node injects verbatim into generated GLSL source (attribute names,
|
|
4
|
+
* uniform names, etc). The root ecosystem rule is "NEVER interpolate
|
|
5
|
+
* user-supplied strings directly into GLSL"; where a name genuinely must
|
|
6
|
+
* appear in the source (e.g. a geometry attribute name the shader reads), it
|
|
7
|
+
* MUST first pass this validator, which throws on anything that isn't a plain
|
|
8
|
+
* GLSL identifier. A name that fails this check could never reference a usable
|
|
9
|
+
* GLSL attribute/uniform anyway, so nothing legitimate is rejected.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isValidGlslIdentifier(name: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Returns `name` if it is a safe GLSL identifier, otherwise throws. Use at the
|
|
14
|
+
* point a name is about to be emitted into shader source.
|
|
15
|
+
*/
|
|
16
|
+
export declare function assertGlslIdentifier(name: string, context: string): string;
|
|
17
|
+
//# sourceMappingURL=glslIdentifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glslIdentifier.d.ts","sourceRoot":"","sources":["../../src/core/glslIdentifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAM3D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAS1E"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GLSL identifier validation — the single security boundary for any string
|
|
3
|
+
* that a node injects verbatim into generated GLSL source (attribute names,
|
|
4
|
+
* uniform names, etc). The root ecosystem rule is "NEVER interpolate
|
|
5
|
+
* user-supplied strings directly into GLSL"; where a name genuinely must
|
|
6
|
+
* appear in the source (e.g. a geometry attribute name the shader reads), it
|
|
7
|
+
* MUST first pass this validator, which throws on anything that isn't a plain
|
|
8
|
+
* GLSL identifier. A name that fails this check could never reference a usable
|
|
9
|
+
* GLSL attribute/uniform anyway, so nothing legitimate is rejected.
|
|
10
|
+
*/
|
|
11
|
+
// GLSL ES identifiers: letter/underscore start, then letters/digits/underscore.
|
|
12
|
+
const GLSL_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
13
|
+
// Reserved: names beginning with `gl_` are reserved by the GLSL spec, and the
|
|
14
|
+
// double-underscore prefix/anywhere is reserved for implementation use.
|
|
15
|
+
export function isValidGlslIdentifier(name) {
|
|
16
|
+
if (typeof name !== 'string')
|
|
17
|
+
return false;
|
|
18
|
+
if (!GLSL_IDENTIFIER.test(name))
|
|
19
|
+
return false;
|
|
20
|
+
if (name.startsWith('gl_'))
|
|
21
|
+
return false;
|
|
22
|
+
if (name.includes('__'))
|
|
23
|
+
return false;
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns `name` if it is a safe GLSL identifier, otherwise throws. Use at the
|
|
28
|
+
* point a name is about to be emitted into shader source.
|
|
29
|
+
*/
|
|
30
|
+
export function assertGlslIdentifier(name, context) {
|
|
31
|
+
if (!isValidGlslIdentifier(name)) {
|
|
32
|
+
throw new Error(`[st-shader-core] ${context}: "${String(name)}" is not a valid GLSL identifier. ` +
|
|
33
|
+
`Only letters, digits and single underscores are allowed (must start with a letter or underscore, ` +
|
|
34
|
+
`may not start with "gl_" or contain "__"). This guards against GLSL injection.`);
|
|
35
|
+
}
|
|
36
|
+
return name;
|
|
37
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { InputSocket } from './core/InputSocket.js';
|
|
|
9
9
|
export { OutputSocket } from './core/OutputSocket.js';
|
|
10
10
|
export { SOCKET_GLSL_TYPE } from './core/SocketType.js';
|
|
11
11
|
export type { SocketType } from './core/SocketType.js';
|
|
12
|
+
export { isValidGlslIdentifier, assertGlslIdentifier } from './core/glslIdentifier.js';
|
|
12
13
|
export { CompileContext } from './core/CompileContext.js';
|
|
13
14
|
export type { CompiledMaterial } from './core/CompileContext.js';
|
|
14
15
|
export { TextureCoordinate } from './nodes/input/TextureCoordinate.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAS,wBAAwB,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAQ,sBAAsB,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAS,qBAAqB,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAQ,sBAAsB,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,MAAO,uBAAuB,CAAA;AAGpD,OAAO,EAAE,WAAW,EAAE,MAAW,uBAAuB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAU,wBAAwB,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,YAAY,EAAE,UAAU,EAAE,MAAO,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export { ProcessNode } from './core/ProcessNode.js';
|
|
|
10
10
|
export { InputSocket } from './core/InputSocket.js';
|
|
11
11
|
export { OutputSocket } from './core/OutputSocket.js';
|
|
12
12
|
export { SOCKET_GLSL_TYPE } from './core/SocketType.js';
|
|
13
|
+
export { isValidGlslIdentifier, assertGlslIdentifier } from './core/glslIdentifier.js';
|
|
13
14
|
// ── Compiler ──────────────────────────────────────────────────────────────────
|
|
14
15
|
export { CompileContext } from './core/CompileContext.js';
|
|
15
16
|
// ── Input nodes ───────────────────────────────────────────────────────────────
|
|
@@ -29,7 +29,7 @@ export declare class Attribute extends InputNode {
|
|
|
29
29
|
/** Sanitized attribute name — only alphanumeric + underscore, used in GLSL. */
|
|
30
30
|
private readonly _safeAttrName;
|
|
31
31
|
constructor(attributeName: string, attributeType?: 'float' | 'vec3');
|
|
32
|
-
getOutputSockets(): Record<string, import("../../
|
|
32
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
33
33
|
vertexInjections(): {
|
|
34
34
|
attrName: string;
|
|
35
35
|
attrType: "float";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Attribute.d.ts","sourceRoot":"","sources":["../../../src/nodes/input/Attribute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"Attribute.d.ts","sourceRoot":"","sources":["../../../src/nodes/input/Attribute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAGlE;;;;;;;;;;;;;;GAcG;AACH,qBAAa,SAAU,SAAQ,SAAS;IACtC,IAAI,QAAQ,WAAyB;IAErC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAE9B,sEAAsE;IAC7D,UAAU,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,CAAuB;IAErE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;IAE5F,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;gBAE1B,aAAa,EAAE,MAAM,EAAE,aAAa,GAAE,OAAO,GAAG,MAAe;IAiB3E,gBAAgB;IAEhB,gBAAgB;;;;;;;;;IAUhB,WAAW,IAAI,MAAM;IAErB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAkBzC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { InputNode } from '../../core/InputNode.js';
|
|
2
|
+
import { assertGlslIdentifier } from '../../core/glslIdentifier.js';
|
|
2
3
|
/**
|
|
3
4
|
* Attribute — Blender "Attribute" input node equivalent.
|
|
4
5
|
* Reads a named custom float or vector attribute from the geometry's BufferAttributes.
|
|
@@ -23,7 +24,13 @@ export class Attribute extends InputNode {
|
|
|
23
24
|
super('Attribute');
|
|
24
25
|
/** 0 = vec3, 1 = float. Stored as number for keyframe/GSAP compat. */
|
|
25
26
|
this.parameters = { attributeType: 0 };
|
|
26
|
-
// SECURITY:
|
|
27
|
+
// SECURITY: the attribute name is emitted verbatim into the vertex shader
|
|
28
|
+
// (`attribute <type> <attributeName>;` and `<varying> = <attributeName>;`),
|
|
29
|
+
// so it must be a valid GLSL identifier — reject anything else here for a
|
|
30
|
+
// clear early error. CompileContext re-validates at emit time as the
|
|
31
|
+
// authoritative boundary. The varying name uses a sanitized copy so it is
|
|
32
|
+
// always safe regardless.
|
|
33
|
+
assertGlslIdentifier(attributeName, 'Attribute name');
|
|
27
34
|
this._safeAttrName = attributeName.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
28
35
|
this.attributeName = attributeName;
|
|
29
36
|
this.parameters.attributeType = attributeType === 'float' ? 1 : 0;
|
|
@@ -15,7 +15,7 @@ export declare class CameraData extends InputNode {
|
|
|
15
15
|
get metadata(): NodeMetadata;
|
|
16
16
|
private readonly _outputs;
|
|
17
17
|
constructor();
|
|
18
|
-
getOutputSockets(): Record<string, import("../../
|
|
18
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
19
19
|
compileCall(ctx: CompileContext): string;
|
|
20
20
|
}
|
|
21
21
|
//# sourceMappingURL=CameraData.d.ts.map
|
|
@@ -16,7 +16,7 @@ export declare class ColorAttribute extends InputNode {
|
|
|
16
16
|
get metadata(): NodeMetadata;
|
|
17
17
|
private readonly _outputs;
|
|
18
18
|
constructor();
|
|
19
|
-
getOutputSockets(): Record<string, import("../../
|
|
19
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
20
20
|
vertexInjections(): {
|
|
21
21
|
attrName: string;
|
|
22
22
|
attrType: "vec3";
|
|
@@ -17,7 +17,7 @@ export declare class Geometry extends InputNode {
|
|
|
17
17
|
get metadata(): NodeMetadata;
|
|
18
18
|
private readonly _outputs;
|
|
19
19
|
constructor();
|
|
20
|
-
getOutputSockets(): Record<string, import("../../
|
|
20
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
21
21
|
compileCall(ctx: CompileContext): string;
|
|
22
22
|
}
|
|
23
23
|
//# sourceMappingURL=Geometry.d.ts.map
|
|
@@ -23,7 +23,7 @@ export declare class HairInfo extends InputNode {
|
|
|
23
23
|
get metadata(): NodeMetadata;
|
|
24
24
|
private readonly _outputs;
|
|
25
25
|
constructor();
|
|
26
|
-
getOutputSockets(): Record<string, import("../../
|
|
26
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
27
27
|
vertexInjections(): ({
|
|
28
28
|
attrName: string;
|
|
29
29
|
attrType: "vec3";
|
|
@@ -20,7 +20,7 @@ export declare class LayerWeight extends InputNode {
|
|
|
20
20
|
constructor(inputs?: {
|
|
21
21
|
blend?: number;
|
|
22
22
|
} | number);
|
|
23
|
-
getOutputSockets(): Record<string, import("../../
|
|
23
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
24
24
|
compileCall(ctx: CompileContext): string;
|
|
25
25
|
}
|
|
26
26
|
//# sourceMappingURL=LayerWeight.d.ts.map
|
|
@@ -46,7 +46,7 @@ export declare class LightPath extends InputNode {
|
|
|
46
46
|
readonly transmissionDepth: "u_st_lp_transmissionDepth";
|
|
47
47
|
};
|
|
48
48
|
constructor();
|
|
49
|
-
getOutputSockets(): Record<string, import("../../
|
|
49
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
50
50
|
/**
|
|
51
51
|
* Register all LightPath uniforms with their rasterizer defaults.
|
|
52
52
|
* CompileContext picks these up and includes them in the compiled
|
|
@@ -16,7 +16,7 @@ export declare class ObjectInfo extends InputNode {
|
|
|
16
16
|
private readonly _outputs;
|
|
17
17
|
private readonly _seed;
|
|
18
18
|
constructor();
|
|
19
|
-
getOutputSockets(): Record<string, import("../../
|
|
19
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
20
20
|
compileCall(ctx: CompileContext): string;
|
|
21
21
|
}
|
|
22
22
|
//# sourceMappingURL=ObjectInfo.d.ts.map
|
|
@@ -21,7 +21,7 @@ export declare class OceanAttribute extends InputNode {
|
|
|
21
21
|
get metadata(): NodeMetadata;
|
|
22
22
|
private readonly _outputs;
|
|
23
23
|
constructor();
|
|
24
|
-
getOutputSockets(): Record<string, import("../../
|
|
24
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
25
25
|
vertexInjections(): {
|
|
26
26
|
attrName: string;
|
|
27
27
|
attrType: "float";
|
|
@@ -20,7 +20,7 @@ export declare class ParticleInfo extends InputNode {
|
|
|
20
20
|
get metadata(): NodeMetadata;
|
|
21
21
|
private readonly _outputs;
|
|
22
22
|
constructor();
|
|
23
|
-
getOutputSockets(): Record<string, import("../../
|
|
23
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
24
24
|
vertexInjections(): {
|
|
25
25
|
attrName: string;
|
|
26
26
|
attrType: "float";
|
|
@@ -13,7 +13,7 @@ export declare class RGB extends InputNode {
|
|
|
13
13
|
private readonly hex;
|
|
14
14
|
private readonly _outputs;
|
|
15
15
|
constructor(color?: string);
|
|
16
|
-
getOutputSockets(): Record<string, import("../../
|
|
16
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
17
17
|
compileCall(ctx: CompileContext): string;
|
|
18
18
|
}
|
|
19
19
|
//# sourceMappingURL=RGB.d.ts.map
|
|
@@ -25,7 +25,7 @@ export declare class ScreenCamera extends InputNode {
|
|
|
25
25
|
get metadata(): NodeMetadata;
|
|
26
26
|
private readonly _outputs;
|
|
27
27
|
constructor();
|
|
28
|
-
getOutputSockets(): Record<string, import("../../
|
|
28
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
29
29
|
/**
|
|
30
30
|
* Declare the camera uniforms that ScreenOutput will inject.
|
|
31
31
|
* They are vec2/vec3/float types that live outside the standard
|
|
@@ -15,7 +15,7 @@ export declare class Tangent extends InputNode {
|
|
|
15
15
|
get metadata(): NodeMetadata;
|
|
16
16
|
private readonly _outputs;
|
|
17
17
|
constructor();
|
|
18
|
-
getOutputSockets(): Record<string, import("../../
|
|
18
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
19
19
|
compileCall(ctx: CompileContext): string;
|
|
20
20
|
}
|
|
21
21
|
//# sourceMappingURL=Tangent.d.ts.map
|