@triforge/shader-core 0.2.1 → 0.3.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 +71 -33
- package/dist/core/CompileContext.d.ts +2 -0
- package/dist/core/CompileContext.d.ts.map +1 -1
- package/dist/core/CompileContext.js +24 -9
- package/dist/core/OutputNode.d.ts.map +1 -1
- package/dist/core/OutputNode.js +1 -0
- package/dist/core/ShaderNode.d.ts +7 -0
- package/dist/core/ShaderNode.d.ts.map +1 -1
- package/dist/core/ShaderNode.js +7 -0
- package/dist/core/SocketType.d.ts +1 -1
- package/dist/core/SocketType.js +1 -1
- package/dist/nodes/output/MaterialOutput.js +2 -2
- package/dist/nodes/process/AddShader.js +3 -3
- package/dist/nodes/process/DiffuseBSDF.js +1 -1
- package/dist/nodes/process/Emission.js +1 -1
- package/dist/nodes/process/GlassBSDF.js +1 -1
- package/dist/nodes/process/GlossyBSDF.js +1 -1
- package/dist/nodes/process/MixShader.js +2 -2
- package/dist/nodes/process/PrincipledBSDF.d.ts +7 -0
- package/dist/nodes/process/PrincipledBSDF.d.ts.map +1 -1
- package/dist/nodes/process/PrincipledBSDF.js +17 -2
- package/dist/nodes/process/PrincipledHair.js +1 -1
- package/dist/nodes/process/PrincipledVolume.js +1 -1
- package/dist/nodes/process/RefractionBSDF.js +1 -1
- package/dist/nodes/process/ShaderScript.d.ts +2 -2
- package/dist/nodes/process/ShaderScript.d.ts.map +1 -1
- package/dist/nodes/process/ShaderScript.js +7 -3
- package/dist/nodes/process/ShaderToRGB.js +2 -2
- package/dist/nodes/process/SheenBSDF.js +1 -1
- package/dist/nodes/process/SpecularBSDF.js +1 -1
- package/dist/nodes/process/SubsurfaceScattering.js +1 -1
- package/dist/nodes/process/ToonBSDF.js +1 -1
- package/dist/nodes/process/TranslucentBSDF.js +1 -1
- package/dist/nodes/process/VolumeAbsorption.js +1 -1
- package/dist/nodes/process/VolumeScatter.js +1 -1
- package/dist/nodes/shader/RayPortal.js +1 -1
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -139,6 +139,15 @@ var ShaderNode = class {
|
|
|
139
139
|
vertexInjections() {
|
|
140
140
|
return [];
|
|
141
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Whether this node's contribution to the compiled material requires
|
|
144
|
+
* `transparent: true` on the resulting THREE.ShaderMaterial (e.g. a
|
|
145
|
+
* `shader`-socket alpha channel that can read below 1.0).
|
|
146
|
+
* Override in nodes that carry alpha semantics — see PrincipledBSDF.
|
|
147
|
+
*/
|
|
148
|
+
wantsTransparency() {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
142
151
|
/**
|
|
143
152
|
* Returns the named output socket.
|
|
144
153
|
* Throws ShaderNodeError if the socket does not exist.
|
|
@@ -295,7 +304,8 @@ var CompileContext = class _CompileContext {
|
|
|
295
304
|
vertexShader: this.buildVertexShader(),
|
|
296
305
|
fragmentShader: this.buildFragmentShader(),
|
|
297
306
|
uniforms: this._uniforms,
|
|
298
|
-
nodes: this.order
|
|
307
|
+
nodes: this.order,
|
|
308
|
+
needsTransparency: this.order.some((node) => node.wantsTransparency())
|
|
299
309
|
};
|
|
300
310
|
}
|
|
301
311
|
/**
|
|
@@ -315,12 +325,23 @@ var CompileContext = class _CompileContext {
|
|
|
315
325
|
resolveInput(socket) {
|
|
316
326
|
if (socket.connection) {
|
|
317
327
|
const varName = this.outputVar(socket.connection.node, socket.connection.name);
|
|
318
|
-
|
|
328
|
+
const fromType = socket.connection.type;
|
|
329
|
+
const toType = socket.type;
|
|
330
|
+
if (toType === "vector" && fromType !== "vector") {
|
|
319
331
|
return `(${varName}).xy`;
|
|
320
332
|
}
|
|
321
|
-
if (
|
|
333
|
+
if (toType === "color" && fromType === "vector") {
|
|
322
334
|
return `vec3(${varName}, 0.0)`;
|
|
323
335
|
}
|
|
336
|
+
if (toType === "color" && fromType === "shader") {
|
|
337
|
+
return `(${varName}).rgb`;
|
|
338
|
+
}
|
|
339
|
+
if (toType === "shader" && fromType === "color") {
|
|
340
|
+
return `vec4(${varName}, 1.0)`;
|
|
341
|
+
}
|
|
342
|
+
if (toType === "shader" && fromType === "vector") {
|
|
343
|
+
return `vec4(${varName}, 0.0, 1.0)`;
|
|
344
|
+
}
|
|
324
345
|
return varName;
|
|
325
346
|
}
|
|
326
347
|
if (socket.uniformName !== null) {
|
|
@@ -436,7 +457,7 @@ var CompileContext = class _CompileContext {
|
|
|
436
457
|
if (from === to) return true;
|
|
437
458
|
if ((from === "shader" || from === "color") && (to === "shader" || to === "color")) return true;
|
|
438
459
|
if ((from === "color" || from === "shader") && to === "vector") return true;
|
|
439
|
-
if (from === "vector" && to === "color") return true;
|
|
460
|
+
if (from === "vector" && (to === "color" || to === "shader")) return true;
|
|
440
461
|
return false;
|
|
441
462
|
}
|
|
442
463
|
// ── GLSL builders ─────────────────────────────────────────────────
|
|
@@ -494,7 +515,7 @@ ${callsBlock}
|
|
|
494
515
|
case "vector":
|
|
495
516
|
return "vec2(vUv)";
|
|
496
517
|
case "shader":
|
|
497
|
-
return "
|
|
518
|
+
return "vec4(0.0, 0.0, 0.0, 1.0)";
|
|
498
519
|
default:
|
|
499
520
|
return "vec3(1.0)";
|
|
500
521
|
}
|
|
@@ -553,7 +574,8 @@ var OutputNode = class extends ShaderNode {
|
|
|
553
574
|
this.material = new ShaderMaterial({
|
|
554
575
|
vertexShader: compiled.vertexShader,
|
|
555
576
|
fragmentShader: compiled.fragmentShader,
|
|
556
|
-
uniforms: compiled.uniforms
|
|
577
|
+
uniforms: compiled.uniforms,
|
|
578
|
+
transparent: compiled.needsTransparency
|
|
557
579
|
});
|
|
558
580
|
if (!this.material.uniforms.uSunDirection) {
|
|
559
581
|
this.material.uniforms.uSunDirection = { value: new Vector3(1, 2, 1).normalize() };
|
|
@@ -577,7 +599,7 @@ var ProcessNode = class extends ShaderNode {
|
|
|
577
599
|
|
|
578
600
|
// src/core/SocketType.ts
|
|
579
601
|
var SOCKET_GLSL_TYPE = {
|
|
580
|
-
shader: "
|
|
602
|
+
shader: "vec4",
|
|
581
603
|
color: "vec3",
|
|
582
604
|
vector: "vec2",
|
|
583
605
|
float: "float"
|
|
@@ -1231,8 +1253,8 @@ var MaterialOutput = class extends OutputNode {
|
|
|
1231
1253
|
return mat;
|
|
1232
1254
|
}
|
|
1233
1255
|
compileCall(ctx) {
|
|
1234
|
-
const sv = this._inputs.surface.isConnected() ? ctx.outputVar(this._inputs.surface.connection.node, this._inputs.surface.connection.name) : "
|
|
1235
|
-
return `gl_FragColor =
|
|
1256
|
+
const sv = this._inputs.surface.isConnected() ? ctx.outputVar(this._inputs.surface.connection.node, this._inputs.surface.connection.name) : "vec4(0.8, 0.8, 0.8, 1.0)";
|
|
1257
|
+
return `gl_FragColor = ${sv};`;
|
|
1236
1258
|
}
|
|
1237
1259
|
};
|
|
1238
1260
|
|
|
@@ -3381,7 +3403,7 @@ float _st_geo(float NdotX, float r) {
|
|
|
3381
3403
|
float k = (r + 1.0) * (r + 1.0) / 8.0;
|
|
3382
3404
|
return NdotX / max(NdotX * (1.0 - k) + k, 1e-7);
|
|
3383
3405
|
}
|
|
3384
|
-
vec3 _st_principledBSDF(vec3 base, float metallic, float roughness, float ior,
|
|
3406
|
+
vec3 _st_principledBSDF(vec3 base, float metallic, float roughness, float ior, vec3 N) {
|
|
3385
3407
|
vec3 V = normalize(cameraPosition - vPosition);
|
|
3386
3408
|
vec3 L = normalize(uSunDirection);
|
|
3387
3409
|
vec3 H = normalize(L + V);
|
|
@@ -3422,9 +3444,23 @@ vec3 _st_principledBSDF(vec3 base, float metallic, float roughness, float ior, f
|
|
|
3422
3444
|
compileDefs() {
|
|
3423
3445
|
return this.glslFunction ?? _PrincipledBSDF.glslFunction;
|
|
3424
3446
|
}
|
|
3447
|
+
/**
|
|
3448
|
+
* Alpha has no channel of its own in the underlying vec3 lighting function —
|
|
3449
|
+
* it's applied as the vec4 alpha component at the call site instead (see
|
|
3450
|
+
* compileCall). transparent:true is needed whenever alpha can read below 1.0:
|
|
3451
|
+
* a non-default literal, or any live/connected value (conservatively true).
|
|
3452
|
+
*/
|
|
3453
|
+
wantsTransparency() {
|
|
3454
|
+
const alphaSocket = this._inputs.alpha;
|
|
3455
|
+
if (alphaSocket.isConnected()) return true;
|
|
3456
|
+
const v = alphaSocket.defaultValue;
|
|
3457
|
+
return typeof v === "number" && v < 1;
|
|
3458
|
+
}
|
|
3425
3459
|
compileCall(ctx) {
|
|
3426
3460
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
3427
|
-
|
|
3461
|
+
const rgb = `_st_principledBSDF(${ctx.resolveInput(this._inputs.baseColor)}, ${ctx.resolveInput(this._inputs.metallic)}, ${ctx.resolveInput(this._inputs.roughness)}, ${ctx.resolveInput(this._inputs.ior)}, ${normal})`;
|
|
3462
|
+
const alpha = ctx.resolveInput(this._inputs.alpha);
|
|
3463
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(${rgb}, ${alpha});`;
|
|
3428
3464
|
}
|
|
3429
3465
|
};
|
|
3430
3466
|
|
|
@@ -3465,7 +3501,7 @@ vec3 _st_emission(vec3 color, float strength) {
|
|
|
3465
3501
|
compileCall(ctx) {
|
|
3466
3502
|
const color = ctx.resolveInput(this._inputs.color);
|
|
3467
3503
|
const strength = ctx.resolveInput(this._inputs.strength);
|
|
3468
|
-
return `
|
|
3504
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_emission(${color}, ${strength}), 1.0);`;
|
|
3469
3505
|
}
|
|
3470
3506
|
};
|
|
3471
3507
|
|
|
@@ -3506,7 +3542,7 @@ vec3 _st_volumeAbsorption(vec3 color, float density) {
|
|
|
3506
3542
|
compileCall(ctx) {
|
|
3507
3543
|
const color = ctx.resolveInput(this._inputs.color);
|
|
3508
3544
|
const density = ctx.resolveInput(this._inputs.density);
|
|
3509
|
-
return `
|
|
3545
|
+
return `vec4 ${ctx.outputVar(this, "Volume")} = vec4(_st_volumeAbsorption(${color}, ${density}), 1.0);`;
|
|
3510
3546
|
}
|
|
3511
3547
|
};
|
|
3512
3548
|
|
|
@@ -3553,7 +3589,7 @@ vec3 _st_volumeScatter(vec3 color, float density, float anisotropy) {
|
|
|
3553
3589
|
const color = ctx.resolveInput(this._inputs.color);
|
|
3554
3590
|
const density = ctx.resolveInput(this._inputs.density);
|
|
3555
3591
|
const anisotropy = ctx.resolveInput(this._inputs.anisotropy);
|
|
3556
|
-
return `
|
|
3592
|
+
return `vec4 ${ctx.outputVar(this, "Volume")} = vec4(_st_volumeScatter(${color}, ${density}, ${anisotropy}), 1.0);`;
|
|
3557
3593
|
}
|
|
3558
3594
|
};
|
|
3559
3595
|
|
|
@@ -3624,7 +3660,7 @@ vec3 _st_principledVolume(
|
|
|
3624
3660
|
const emissionStrength = ctx.resolveInput(this._inputs.emissionStrength);
|
|
3625
3661
|
const blackbodyIntensity = ctx.resolveInput(this._inputs.blackbodyIntensity);
|
|
3626
3662
|
const temperature = ctx.resolveInput(this._inputs.temperature);
|
|
3627
|
-
return `
|
|
3663
|
+
return `vec4 ${ctx.outputVar(this, "Volume")} = vec4(_st_principledVolume(${color}, ${density}, ${anisotropy}, ${absorptionColor}, ${emissionColor}, ${emissionStrength}, ${blackbodyIntensity}, ${temperature}), 1.0);`;
|
|
3628
3664
|
}
|
|
3629
3665
|
};
|
|
3630
3666
|
|
|
@@ -3646,7 +3682,7 @@ var MixShader = class _MixShader extends ProcessNode {
|
|
|
3646
3682
|
}
|
|
3647
3683
|
static {
|
|
3648
3684
|
this.glslFunction = `
|
|
3649
|
-
|
|
3685
|
+
vec4 _st_mixShader(float fac, vec4 a, vec4 b) {
|
|
3650
3686
|
return mix(a, b, clamp(fac, 0.0, 1.0));
|
|
3651
3687
|
}`;
|
|
3652
3688
|
}
|
|
@@ -3672,7 +3708,7 @@ vec3 _st_mixShader(float fac, vec3 a, vec3 b) {
|
|
|
3672
3708
|
const fac = ctx.resolveInput(this._inputs.fac);
|
|
3673
3709
|
const shader1 = ctx.resolveInput(this._inputs.shader1);
|
|
3674
3710
|
const shader2 = ctx.resolveInput(this._inputs.shader2);
|
|
3675
|
-
return `
|
|
3711
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = _st_mixShader(${fac}, ${shader1}, ${shader2});`;
|
|
3676
3712
|
}
|
|
3677
3713
|
};
|
|
3678
3714
|
|
|
@@ -3689,8 +3725,8 @@ var AddShader = class _AddShader extends ProcessNode {
|
|
|
3689
3725
|
}
|
|
3690
3726
|
static {
|
|
3691
3727
|
this.glslFunction = `
|
|
3692
|
-
|
|
3693
|
-
return a + b;
|
|
3728
|
+
vec4 _st_addShader(vec4 a, vec4 b) {
|
|
3729
|
+
return vec4(a.rgb + b.rgb, max(a.a, b.a));
|
|
3694
3730
|
}`;
|
|
3695
3731
|
}
|
|
3696
3732
|
constructor(inputs = {}) {
|
|
@@ -3713,7 +3749,7 @@ vec3 _st_addShader(vec3 a, vec3 b) {
|
|
|
3713
3749
|
compileCall(ctx) {
|
|
3714
3750
|
const s1 = ctx.resolveInput(this._inputs.shader1);
|
|
3715
3751
|
const s2 = ctx.resolveInput(this._inputs.shader2);
|
|
3716
|
-
return `
|
|
3752
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = _st_addShader(${s1}, ${s2});`;
|
|
3717
3753
|
}
|
|
3718
3754
|
};
|
|
3719
3755
|
|
|
@@ -3810,7 +3846,7 @@ vec3 _st_diffuseBSDF(vec3 color, float roughness, vec3 N) {
|
|
|
3810
3846
|
const color = ctx.resolveInput(this._inputs.color);
|
|
3811
3847
|
const roughness = ctx.resolveInput(this._inputs.roughness);
|
|
3812
3848
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
3813
|
-
return `
|
|
3849
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_diffuseBSDF(${color}, ${roughness}, ${normal}), 1.0);`;
|
|
3814
3850
|
}
|
|
3815
3851
|
};
|
|
3816
3852
|
|
|
@@ -3864,7 +3900,7 @@ vec3 _st_glossyBSDF(vec3 color, float roughness, vec3 N) {
|
|
|
3864
3900
|
const color = ctx.resolveInput(this._inputs.color);
|
|
3865
3901
|
const roughness = ctx.resolveInput(this._inputs.roughness);
|
|
3866
3902
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
3867
|
-
return `
|
|
3903
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_glossyBSDF(${color}, ${roughness}, ${normal}), 1.0);`;
|
|
3868
3904
|
}
|
|
3869
3905
|
};
|
|
3870
3906
|
|
|
@@ -3913,7 +3949,7 @@ vec3 _st_refractionBSDF(vec3 color, float roughness, float ior, vec3 N) {
|
|
|
3913
3949
|
const roughness = ctx.resolveInput(this._inputs.roughness);
|
|
3914
3950
|
const ior = ctx.resolveInput(this._inputs.ior);
|
|
3915
3951
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
3916
|
-
return `
|
|
3952
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_refractionBSDF(${color}, ${roughness}, ${ior}, ${normal}), 1.0);`;
|
|
3917
3953
|
}
|
|
3918
3954
|
};
|
|
3919
3955
|
|
|
@@ -3968,7 +4004,7 @@ vec3 _st_glassBSDF(vec3 color, float roughness, float ior, vec3 N) {
|
|
|
3968
4004
|
const roughness = ctx.resolveInput(this._inputs.roughness);
|
|
3969
4005
|
const ior = ctx.resolveInput(this._inputs.ior);
|
|
3970
4006
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
3971
|
-
return `
|
|
4007
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_glassBSDF(${color}, ${roughness}, ${ior}, ${normal}), 1.0);`;
|
|
3972
4008
|
}
|
|
3973
4009
|
};
|
|
3974
4010
|
|
|
@@ -4020,7 +4056,7 @@ vec3 _st_sheenBSDF(vec3 color, float roughness, vec3 N) {
|
|
|
4020
4056
|
const color = ctx.resolveInput(this._inputs.color);
|
|
4021
4057
|
const roughness = ctx.resolveInput(this._inputs.roughness);
|
|
4022
4058
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
4023
|
-
return `
|
|
4059
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_sheenBSDF(${color}, ${roughness}, ${normal}), 1.0);`;
|
|
4024
4060
|
}
|
|
4025
4061
|
};
|
|
4026
4062
|
|
|
@@ -4069,7 +4105,7 @@ vec3 _st_sss(vec3 color, float scale, vec3 radius, vec3 N) {
|
|
|
4069
4105
|
const scale = ctx.resolveInput(this._inputs.scale);
|
|
4070
4106
|
const [r, g, b] = this.radius;
|
|
4071
4107
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
4072
|
-
return `
|
|
4108
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_sss(${color}, ${scale}, vec3(${r.toFixed(4)}, ${g.toFixed(4)}, ${b.toFixed(4)}), ${normal}), 1.0);`;
|
|
4073
4109
|
}
|
|
4074
4110
|
};
|
|
4075
4111
|
|
|
@@ -4117,7 +4153,7 @@ vec3 _st_toonBSDF(vec3 color, float size, float smoothWidth, vec3 N) {
|
|
|
4117
4153
|
const size = ctx.resolveInput(this._inputs.size);
|
|
4118
4154
|
const smoothWidth = ctx.resolveInput(this._inputs.smooth);
|
|
4119
4155
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
4120
|
-
return `
|
|
4156
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_toonBSDF(${color}, ${size}, ${smoothWidth}, ${normal}), 1.0);`;
|
|
4121
4157
|
}
|
|
4122
4158
|
};
|
|
4123
4159
|
|
|
@@ -4174,7 +4210,7 @@ vec3 _st_specularBSDF(vec3 base, vec3 spec, float roughness, vec3 N) {
|
|
|
4174
4210
|
const spec = ctx.resolveInput(this._inputs.specular);
|
|
4175
4211
|
const roughness = ctx.resolveInput(this._inputs.roughness);
|
|
4176
4212
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
4177
|
-
return `
|
|
4213
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_specularBSDF(${base}, ${spec}, ${roughness}, ${normal}), 1.0);`;
|
|
4178
4214
|
}
|
|
4179
4215
|
};
|
|
4180
4216
|
|
|
@@ -4217,7 +4253,7 @@ vec3 _st_translucentBSDF(vec3 color, vec3 N) {
|
|
|
4217
4253
|
compileCall(ctx) {
|
|
4218
4254
|
const color = ctx.resolveInput(this._inputs.color);
|
|
4219
4255
|
const normal = this._inputs.normal.isConnected() ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name) : "normalize(vNormal)";
|
|
4220
|
-
return `
|
|
4256
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_translucentBSDF(${color}, ${normal}), 1.0);`;
|
|
4221
4257
|
}
|
|
4222
4258
|
};
|
|
4223
4259
|
|
|
@@ -4349,7 +4385,7 @@ vec3 _st_principledHair(
|
|
|
4349
4385
|
const randomRoughness = ctx.resolveInput(this._inputs.randomRoughness);
|
|
4350
4386
|
const random = ctx.resolveInput(this._inputs.random);
|
|
4351
4387
|
const tangent = this._inputs.tangent.isConnected() ? ctx.outputVar(this._inputs.tangent.connection.node, this._inputs.tangent.connection.name) : "normalize(vStrandTangent)";
|
|
4352
|
-
return `
|
|
4388
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(_st_principledHair(${color}, ${roughness}, ${radialRoughness}, ${coat}, ${ior}, ${offset}, ${randomColor}, ${randomRoughness}, ${random}, ${tangent}), 1.0);`;
|
|
4353
4389
|
}
|
|
4354
4390
|
};
|
|
4355
4391
|
|
|
@@ -4664,8 +4700,8 @@ var ShaderToRGB = class extends ProcessNode {
|
|
|
4664
4700
|
const cv = ctx.outputVar(this, "Color");
|
|
4665
4701
|
const av = ctx.outputVar(this, "Alpha");
|
|
4666
4702
|
return [
|
|
4667
|
-
`vec3 ${cv} = ${shader};`,
|
|
4668
|
-
`float ${av} =
|
|
4703
|
+
`vec3 ${cv} = (${shader}).rgb;`,
|
|
4704
|
+
`float ${av} = (${shader}).a;`
|
|
4669
4705
|
].join("\n ");
|
|
4670
4706
|
}
|
|
4671
4707
|
};
|
|
@@ -4951,11 +4987,13 @@ var ShaderScript = class extends ProcessNode {
|
|
|
4951
4987
|
_socketGlslType(type) {
|
|
4952
4988
|
if (type === "float") return "float";
|
|
4953
4989
|
if (type === "vector") return "vec2";
|
|
4990
|
+
if (type === "shader") return "vec4";
|
|
4954
4991
|
return "vec3";
|
|
4955
4992
|
}
|
|
4956
4993
|
_declGlslType(type) {
|
|
4957
4994
|
if (type === "float") return "float";
|
|
4958
4995
|
if (type === "vector") return "vec2";
|
|
4996
|
+
if (type === "shader") return "vec4";
|
|
4959
4997
|
return "vec3";
|
|
4960
4998
|
}
|
|
4961
4999
|
};
|
|
@@ -5537,7 +5575,7 @@ var RayPortal = class extends ProcessNode {
|
|
|
5537
5575
|
const color = ctx.resolveInput(this._inputs.color);
|
|
5538
5576
|
const rawBlend = this.parameters.blend;
|
|
5539
5577
|
const blend = Number.isFinite(rawBlend) ? Math.min(Math.max(rawBlend, 0), 1).toFixed(4) : "1.0000";
|
|
5540
|
-
return `
|
|
5578
|
+
return `vec4 ${ctx.outputVar(this, "BSDF")} = vec4(${color} * ${blend}, 1.0);`;
|
|
5541
5579
|
}
|
|
5542
5580
|
};
|
|
5543
5581
|
export {
|
|
@@ -8,6 +8,8 @@ export interface CompiledMaterial {
|
|
|
8
8
|
value: unknown;
|
|
9
9
|
}>;
|
|
10
10
|
nodes: ShaderNode[];
|
|
11
|
+
/** True when any node in the graph carries alpha that can read below 1.0 (see ShaderNode.wantsTransparency). */
|
|
12
|
+
needsTransparency: boolean;
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
13
15
|
* Walks the node graph from an OutputNode, validates all connections,
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,EAAO,MAAM,CAAA;IACzB,cAAc,EAAK,MAAM,CAAA;IACzB,QAAQ,EAAW,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACrD,KAAK,EAAc,UAAU,EAAE,CAAA;IAC/B,gHAAgH;IAChH,iBAAiB,EAAE,OAAO,CAAA;CAC3B;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;IAejD;;;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;IAgDlD,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;IAwBjB,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"}
|
|
@@ -35,6 +35,7 @@ export class CompileContext {
|
|
|
35
35
|
fragmentShader: this.buildFragmentShader(),
|
|
36
36
|
uniforms: this._uniforms,
|
|
37
37
|
nodes: this.order,
|
|
38
|
+
needsTransparency: this.order.some(node => node.wantsTransparency()),
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
/**
|
|
@@ -54,14 +55,28 @@ export class CompileContext {
|
|
|
54
55
|
resolveInput(socket) {
|
|
55
56
|
if (socket.connection) {
|
|
56
57
|
const varName = this.outputVar(socket.connection.node, socket.connection.name);
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
const fromType = socket.connection.type;
|
|
59
|
+
const toType = socket.type;
|
|
60
|
+
// vec3/vec4 (color/shader) → vec2 (vector) implicit narrowing, e.g. Mapping.Vector → ImageTexture.vector
|
|
61
|
+
if (toType === 'vector' && fromType !== 'vector') {
|
|
59
62
|
return `(${varName}).xy`;
|
|
60
63
|
}
|
|
61
|
-
// vec2 (vector) → vec3 (color) implicit
|
|
62
|
-
if (
|
|
64
|
+
// vec2 (vector) → vec3 (color) implicit widening, e.g. TextureCoordinate.UV → Mapping.vector
|
|
65
|
+
if (toType === 'color' && fromType === 'vector') {
|
|
63
66
|
return `vec3(${varName}, 0.0)`;
|
|
64
67
|
}
|
|
68
|
+
// vec4 (shader) → vec3 (color) implicit narrowing — drop alpha, e.g. ShaderToRGB-style consumption
|
|
69
|
+
if (toType === 'color' && fromType === 'shader') {
|
|
70
|
+
return `(${varName}).rgb`;
|
|
71
|
+
}
|
|
72
|
+
// vec3 (color) → vec4 (shader) implicit widening — opaque alpha
|
|
73
|
+
if (toType === 'shader' && fromType === 'color') {
|
|
74
|
+
return `vec4(${varName}, 1.0)`;
|
|
75
|
+
}
|
|
76
|
+
// vec2 (vector) → vec4 (shader) implicit widening — opaque alpha
|
|
77
|
+
if (toType === 'shader' && fromType === 'vector') {
|
|
78
|
+
return `vec4(${varName}, 0.0, 1.0)`;
|
|
79
|
+
}
|
|
65
80
|
return varName;
|
|
66
81
|
}
|
|
67
82
|
if (socket.uniformName !== null) {
|
|
@@ -200,15 +215,15 @@ export class CompileContext {
|
|
|
200
215
|
typesCompatible(from, to) {
|
|
201
216
|
if (from === to)
|
|
202
217
|
return true;
|
|
203
|
-
// shader and color
|
|
218
|
+
// shader (vec4) and color (vec3) freely convert — narrow via .rgb, widen via vec4(v, 1.0)
|
|
204
219
|
if ((from === 'shader' || from === 'color') && (to === 'shader' || to === 'color'))
|
|
205
220
|
return true;
|
|
206
|
-
// vec3 (color/shader) implicitly narrows to vec2 (vector) via .xy, mirroring Blender's
|
|
221
|
+
// vec3/vec4 (color/shader) implicitly narrows to vec2 (vector) via .xy, mirroring Blender's
|
|
207
222
|
// Mapping (vector output) → Image Texture Vector panning graph
|
|
208
223
|
if ((from === 'color' || from === 'shader') && to === 'vector')
|
|
209
224
|
return true;
|
|
210
|
-
// vec2 (vector) implicitly widens to vec3 (color)
|
|
211
|
-
if (from === 'vector' && to === 'color')
|
|
225
|
+
// vec2 (vector) implicitly widens to vec3 (color) or vec4 (shader)
|
|
226
|
+
if (from === 'vector' && (to === 'color' || to === 'shader'))
|
|
212
227
|
return true;
|
|
213
228
|
return false;
|
|
214
229
|
}
|
|
@@ -277,7 +292,7 @@ ${callsBlock}
|
|
|
277
292
|
case 'vector':
|
|
278
293
|
return 'vec2(vUv)';
|
|
279
294
|
case 'shader':
|
|
280
|
-
return '
|
|
295
|
+
return 'vec4(0.0, 0.0, 0.0, 1.0)';
|
|
281
296
|
default:
|
|
282
297
|
return 'vec3(1.0)';
|
|
283
298
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OutputNode.d.ts","sourceRoot":"","sources":["../../src/core/OutputNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,EAAE,cAAc,EAAW,MAAM,OAAO,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD;;;;GAIG;AACH,8BAAsB,UAAW,SAAQ,UAAU;IACjD,+EAA+E;IAC/E,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAO;IAEtC,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAIhD,WAAW,IAAI,MAAM;IAIrB;;;;;;;;;;;;;OAaG;IACH,OAAO,IAAI,cAAc;
|
|
1
|
+
{"version":3,"file":"OutputNode.d.ts","sourceRoot":"","sources":["../../src/core/OutputNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,EAAE,cAAc,EAAW,MAAM,OAAO,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD;;;;GAIG;AACH,8BAAsB,UAAW,SAAQ,UAAU;IACjD,+EAA+E;IAC/E,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAO;IAEtC,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAIhD,WAAW,IAAI,MAAM;IAIrB;;;;;;;;;;;;;OAaG;IACH,OAAO,IAAI,cAAc;CA0B1B"}
|
package/dist/core/OutputNode.js
CHANGED
|
@@ -39,6 +39,7 @@ export class OutputNode extends ShaderNode {
|
|
|
39
39
|
vertexShader: compiled.vertexShader,
|
|
40
40
|
fragmentShader: compiled.fragmentShader,
|
|
41
41
|
uniforms: compiled.uniforms,
|
|
42
|
+
transparent: compiled.needsTransparency,
|
|
42
43
|
});
|
|
43
44
|
// Inject default scene-lighting uniforms used by PrincipledBSDF.
|
|
44
45
|
// Users can override these after compile() to match their scene lights.
|
|
@@ -61,6 +61,13 @@ export declare abstract class ShaderNode {
|
|
|
61
61
|
attrType: 'float' | 'vec2' | 'vec3';
|
|
62
62
|
varyingName: string;
|
|
63
63
|
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Whether this node's contribution to the compiled material requires
|
|
66
|
+
* `transparent: true` on the resulting THREE.ShaderMaterial (e.g. a
|
|
67
|
+
* `shader`-socket alpha channel that can read below 1.0).
|
|
68
|
+
* Override in nodes that carry alpha semantics — see PrincipledBSDF.
|
|
69
|
+
*/
|
|
70
|
+
wantsTransparency(): boolean;
|
|
64
71
|
/**
|
|
65
72
|
* Returns the named output socket.
|
|
66
73
|
* Throws ShaderNodeError if the socket does not exist.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShaderNode.d.ts","sourceRoot":"","sources":["../../src/core/ShaderNode.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAsBjD,6DAA6D;AAC7D,KAAK,QAAQ,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;AAE/C,8CAA8C;AAC9C,KAAK,SAAS,GAAG,UAAU,CAAA;AAE3B,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAK,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAK,MAAM,CAAA;IAChB,IAAI,EAAM,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,8BAAsB,UAAU;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;;;OAKG;IACH,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAEvC;;;;;;;;OAQG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAK;IAElE,2EAA2E;IAC3E,OAAO,CAAC,WAAW,CAAmC;IACtD,yDAAyD;IACzD,OAAO,CAAC,YAAY,CAAkC;gBAE1C,QAAQ,EAAE,MAAM;IAI5B,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAA;IAC/B,QAAQ,KAAK,QAAQ,IAAI,YAAY,CAAA;IAErC,QAAQ,CAAC,eAAe,IAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACjE,QAAQ,CAAC,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAEzD;;;;;;;;;OASG;IACH,gBAAgB,IAAI,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAIzG;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;IAelC;;;OAGG;IACH,QAAQ,CAAC,WAAW,IAAI,MAAM;IAE9B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,qBAAqB,EAAE,cAAc,GAAG,MAAM;IAE/E;;;;OAIG;IACH,MAAM,CAAC,mBAAmB,UAAQ;IAElC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,YAAY,CACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAkCvC;;;;;OAKG;IACH,SAAS,CAAC,aAAa,CACrB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAC9B,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAQ/B;;;;OAIG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,IAAI;CAqBpE"}
|
|
1
|
+
{"version":3,"file":"ShaderNode.d.ts","sourceRoot":"","sources":["../../src/core/ShaderNode.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAsBjD,6DAA6D;AAC7D,KAAK,QAAQ,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;AAE/C,8CAA8C;AAC9C,KAAK,SAAS,GAAG,UAAU,CAAA;AAE3B,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAK,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAK,MAAM,CAAA;IAChB,IAAI,EAAM,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,8BAAsB,UAAU;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;;;OAKG;IACH,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAEvC;;;;;;;;OAQG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAK;IAElE,2EAA2E;IAC3E,OAAO,CAAC,WAAW,CAAmC;IACtD,yDAAyD;IACzD,OAAO,CAAC,YAAY,CAAkC;gBAE1C,QAAQ,EAAE,MAAM;IAI5B,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAA;IAC/B,QAAQ,KAAK,QAAQ,IAAI,YAAY,CAAA;IAErC,QAAQ,CAAC,eAAe,IAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACjE,QAAQ,CAAC,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAEzD;;;;;;;;;OASG;IACH,gBAAgB,IAAI,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAIzG;;;;;OAKG;IACH,iBAAiB,IAAI,OAAO;IAE5B;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;IAelC;;;OAGG;IACH,QAAQ,CAAC,WAAW,IAAI,MAAM;IAE9B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,qBAAqB,EAAE,cAAc,GAAG,MAAM;IAE/E;;;;OAIG;IACH,MAAM,CAAC,mBAAmB,UAAQ;IAElC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,YAAY,CACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAkCvC;;;;;OAKG;IACH,SAAS,CAAC,aAAa,CACrB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAC9B,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAQ/B;;;;OAIG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,IAAI;CAqBpE"}
|
package/dist/core/ShaderNode.js
CHANGED
|
@@ -60,6 +60,13 @@ export class ShaderNode {
|
|
|
60
60
|
vertexInjections() {
|
|
61
61
|
return [];
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Whether this node's contribution to the compiled material requires
|
|
65
|
+
* `transparent: true` on the resulting THREE.ShaderMaterial (e.g. a
|
|
66
|
+
* `shader`-socket alpha channel that can read below 1.0).
|
|
67
|
+
* Override in nodes that carry alpha semantics — see PrincipledBSDF.
|
|
68
|
+
*/
|
|
69
|
+
wantsTransparency() { return false; }
|
|
63
70
|
/**
|
|
64
71
|
* Returns the named output socket.
|
|
65
72
|
* Throws ShaderNodeError if the socket does not exist.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Socket types mirror Blender's socket colours.
|
|
3
3
|
*
|
|
4
|
-
* shader — yellow — BSDF / material output
|
|
4
|
+
* shader — yellow — BSDF / material output — vec4 RGB + alpha
|
|
5
5
|
* color — yellow-green — vec3 RGB
|
|
6
6
|
* vector — purple — vec2 / vec3 spatial
|
|
7
7
|
* float — grey — single scalar
|
package/dist/core/SocketType.js
CHANGED
|
@@ -112,7 +112,7 @@ export class MaterialOutput extends OutputNode {
|
|
|
112
112
|
compileCall(ctx) {
|
|
113
113
|
const sv = this._inputs.surface.isConnected()
|
|
114
114
|
? ctx.outputVar(this._inputs.surface.connection.node, this._inputs.surface.connection.name)
|
|
115
|
-
: '
|
|
116
|
-
return `gl_FragColor =
|
|
115
|
+
: 'vec4(0.8, 0.8, 0.8, 1.0)';
|
|
116
|
+
return `gl_FragColor = ${sv};`;
|
|
117
117
|
}
|
|
118
118
|
}
|
|
@@ -26,11 +26,11 @@ export class AddShader extends ProcessNode {
|
|
|
26
26
|
compileCall(ctx) {
|
|
27
27
|
const s1 = ctx.resolveInput(this._inputs.shader1);
|
|
28
28
|
const s2 = ctx.resolveInput(this._inputs.shader2);
|
|
29
|
-
return `
|
|
29
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = _st_addShader(${s1}, ${s2});`;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
AddShader.instanceSpecificDef = false;
|
|
33
33
|
AddShader.glslFunction = `
|
|
34
|
-
|
|
35
|
-
return a + b;
|
|
34
|
+
vec4 _st_addShader(vec4 a, vec4 b) {
|
|
35
|
+
return vec4(a.rgb + b.rgb, max(a.a, b.a));
|
|
36
36
|
}`;
|
|
@@ -29,7 +29,7 @@ export class DiffuseBSDF extends ProcessNode {
|
|
|
29
29
|
const normal = this._inputs.normal.isConnected()
|
|
30
30
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
31
31
|
: 'normalize(vNormal)';
|
|
32
|
-
return `
|
|
32
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_diffuseBSDF(${color}, ${roughness}, ${normal}), 1.0);`;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
DiffuseBSDF.instanceSpecificDef = false;
|
|
@@ -26,7 +26,7 @@ export class Emission extends ProcessNode {
|
|
|
26
26
|
compileCall(ctx) {
|
|
27
27
|
const color = ctx.resolveInput(this._inputs.color);
|
|
28
28
|
const strength = ctx.resolveInput(this._inputs.strength);
|
|
29
|
-
return `
|
|
29
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_emission(${color}, ${strength}), 1.0);`;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
Emission.instanceSpecificDef = false;
|
|
@@ -31,7 +31,7 @@ export class GlassBSDF extends ProcessNode {
|
|
|
31
31
|
const normal = this._inputs.normal.isConnected()
|
|
32
32
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
33
33
|
: 'normalize(vNormal)';
|
|
34
|
-
return `
|
|
34
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_glassBSDF(${color}, ${roughness}, ${ior}, ${normal}), 1.0);`;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
GlassBSDF.instanceSpecificDef = false;
|
|
@@ -29,7 +29,7 @@ export class GlossyBSDF extends ProcessNode {
|
|
|
29
29
|
const normal = this._inputs.normal.isConnected()
|
|
30
30
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
31
31
|
: 'normalize(vNormal)';
|
|
32
|
-
return `
|
|
32
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_glossyBSDF(${color}, ${roughness}, ${normal}), 1.0);`;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
GlossyBSDF.instanceSpecificDef = false;
|
|
@@ -37,11 +37,11 @@ export class MixShader extends ProcessNode {
|
|
|
37
37
|
const fac = ctx.resolveInput(this._inputs.fac);
|
|
38
38
|
const shader1 = ctx.resolveInput(this._inputs.shader1);
|
|
39
39
|
const shader2 = ctx.resolveInput(this._inputs.shader2);
|
|
40
|
-
return `
|
|
40
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = _st_mixShader(${fac}, ${shader1}, ${shader2});`;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
MixShader.instanceSpecificDef = false;
|
|
44
44
|
MixShader.glslFunction = `
|
|
45
|
-
|
|
45
|
+
vec4 _st_mixShader(float fac, vec4 a, vec4 b) {
|
|
46
46
|
return mix(a, b, clamp(fac, 0.0, 1.0));
|
|
47
47
|
}`;
|
|
@@ -27,6 +27,13 @@ export declare class PrincipledBSDF extends ProcessNode {
|
|
|
27
27
|
getInputSockets(): Record<string, import("../../index.js").InputSocket<unknown>>;
|
|
28
28
|
getOutputSockets(): Record<string, OutputSocket>;
|
|
29
29
|
compileDefs(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Alpha has no channel of its own in the underlying vec3 lighting function —
|
|
32
|
+
* it's applied as the vec4 alpha component at the call site instead (see
|
|
33
|
+
* compileCall). transparent:true is needed whenever alpha can read below 1.0:
|
|
34
|
+
* a non-default literal, or any live/connected value (conservatively true).
|
|
35
|
+
*/
|
|
36
|
+
wantsTransparency(): boolean;
|
|
30
37
|
compileCall(ctx: CompileContext): string;
|
|
31
38
|
}
|
|
32
39
|
//# sourceMappingURL=PrincipledBSDF.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrincipledBSDF.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/PrincipledBSDF.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;IACjC,QAAQ,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IACjC,SAAS,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;IACjC,GAAG,CAAC,EAAQ,YAAY,GAAG,MAAM,CAAA;IACjC,KAAK,CAAC,EAAM,YAAY,GAAG,MAAM,CAAA;IACjC,MAAM,CAAC,EAAK,YAAY,CAAA;CACzB;AAED;;;;;GAKG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC7C,IAAI,QAAQ,WAA8B;IAC1C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAuCnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,oBAAyB;IAa7C,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"PrincipledBSDF.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/PrincipledBSDF.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;IACjC,QAAQ,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IACjC,SAAS,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;IACjC,GAAG,CAAC,EAAQ,YAAY,GAAG,MAAM,CAAA;IACjC,KAAK,CAAC,EAAM,YAAY,GAAG,MAAM,CAAA;IACjC,MAAM,CAAC,EAAK,YAAY,CAAA;CACzB;AAED;;;;;GAKG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC7C,IAAI,QAAQ,WAA8B;IAC1C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAuCnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,oBAAyB;IAa7C,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX;;;;;OAKG;IACH,iBAAiB,IAAI,OAAO;IAO5B,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAQzC"}
|
|
@@ -25,11 +25,26 @@ export class PrincipledBSDF extends ProcessNode {
|
|
|
25
25
|
getInputSockets() { return this._inputs; }
|
|
26
26
|
getOutputSockets() { return this._outputs; }
|
|
27
27
|
compileDefs() { return this.glslFunction ?? PrincipledBSDF.glslFunction; }
|
|
28
|
+
/**
|
|
29
|
+
* Alpha has no channel of its own in the underlying vec3 lighting function —
|
|
30
|
+
* it's applied as the vec4 alpha component at the call site instead (see
|
|
31
|
+
* compileCall). transparent:true is needed whenever alpha can read below 1.0:
|
|
32
|
+
* a non-default literal, or any live/connected value (conservatively true).
|
|
33
|
+
*/
|
|
34
|
+
wantsTransparency() {
|
|
35
|
+
const alphaSocket = this._inputs.alpha;
|
|
36
|
+
if (alphaSocket.isConnected())
|
|
37
|
+
return true;
|
|
38
|
+
const v = alphaSocket.defaultValue;
|
|
39
|
+
return typeof v === 'number' && v < 1.0;
|
|
40
|
+
}
|
|
28
41
|
compileCall(ctx) {
|
|
29
42
|
const normal = this._inputs.normal.isConnected()
|
|
30
43
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
31
44
|
: 'normalize(vNormal)';
|
|
32
|
-
|
|
45
|
+
const rgb = `_st_principledBSDF(${ctx.resolveInput(this._inputs.baseColor)}, ${ctx.resolveInput(this._inputs.metallic)}, ${ctx.resolveInput(this._inputs.roughness)}, ${ctx.resolveInput(this._inputs.ior)}, ${normal})`;
|
|
46
|
+
const alpha = ctx.resolveInput(this._inputs.alpha);
|
|
47
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(${rgb}, ${alpha});`;
|
|
33
48
|
}
|
|
34
49
|
}
|
|
35
50
|
PrincipledBSDF.instanceSpecificDef = false;
|
|
@@ -54,7 +69,7 @@ float _st_geo(float NdotX, float r) {
|
|
|
54
69
|
float k = (r + 1.0) * (r + 1.0) / 8.0;
|
|
55
70
|
return NdotX / max(NdotX * (1.0 - k) + k, 1e-7);
|
|
56
71
|
}
|
|
57
|
-
vec3 _st_principledBSDF(vec3 base, float metallic, float roughness, float ior,
|
|
72
|
+
vec3 _st_principledBSDF(vec3 base, float metallic, float roughness, float ior, vec3 N) {
|
|
58
73
|
vec3 V = normalize(cameraPosition - vPosition);
|
|
59
74
|
vec3 L = normalize(uSunDirection);
|
|
60
75
|
vec3 H = normalize(L + V);
|
|
@@ -59,7 +59,7 @@ export class PrincipledHair extends ProcessNode {
|
|
|
59
59
|
const tangent = this._inputs.tangent.isConnected()
|
|
60
60
|
? ctx.outputVar(this._inputs.tangent.connection.node, this._inputs.tangent.connection.name)
|
|
61
61
|
: 'normalize(vStrandTangent)'; // fallback: read attribute directly if not connected
|
|
62
|
-
return `
|
|
62
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_principledHair(${color}, ${roughness}, ${radialRoughness}, ${coat}, ${ior}, ${offset}, ${randomColor}, ${randomRoughness}, ${random}, ${tangent}), 1.0);`;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
PrincipledHair.instanceSpecificDef = false;
|
|
@@ -39,7 +39,7 @@ export class PrincipledVolume extends ProcessNode {
|
|
|
39
39
|
const emissionStrength = ctx.resolveInput(this._inputs.emissionStrength);
|
|
40
40
|
const blackbodyIntensity = ctx.resolveInput(this._inputs.blackbodyIntensity);
|
|
41
41
|
const temperature = ctx.resolveInput(this._inputs.temperature);
|
|
42
|
-
return `
|
|
42
|
+
return `vec4 ${ctx.outputVar(this, 'Volume')} = vec4(_st_principledVolume(${color}, ${density}, ${anisotropy}, ${absorptionColor}, ${emissionColor}, ${emissionStrength}, ${blackbodyIntensity}, ${temperature}), 1.0);`;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
PrincipledVolume.instanceSpecificDef = false;
|
|
@@ -32,7 +32,7 @@ export class RefractionBSDF extends ProcessNode {
|
|
|
32
32
|
const normal = this._inputs.normal.isConnected()
|
|
33
33
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
34
34
|
: 'normalize(vNormal)';
|
|
35
|
-
return `
|
|
35
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_refractionBSDF(${color}, ${roughness}, ${ior}, ${normal}), 1.0);`;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
RefractionBSDF.instanceSpecificDef = false;
|
|
@@ -7,7 +7,7 @@ import type { OutputSocket } from '../../core/OutputSocket.js';
|
|
|
7
7
|
* 'float' → float (uniform or literal)
|
|
8
8
|
* 'color' → vec3 (uniform or literal hex / [r,g,b])
|
|
9
9
|
* 'vector' → vec2 (UV coordinates)
|
|
10
|
-
* 'shader' →
|
|
10
|
+
* 'shader' → vec4 (BSDF connection, rgb + alpha)
|
|
11
11
|
*/
|
|
12
12
|
export type ScriptInputDecl = ['float' | 'color' | 'vector' | 'shader', unknown];
|
|
13
13
|
/** Output socket type map: socketName → glslType */
|
|
@@ -49,7 +49,7 @@ export interface ShaderScriptConfig {
|
|
|
49
49
|
* Inside the GLSL body:
|
|
50
50
|
* • Input sockets are available as local variables with the exact name you declared.
|
|
51
51
|
* • Output sockets must be assigned by name before the block ends.
|
|
52
|
-
* • GLSL types: 'float' → float, 'color'
|
|
52
|
+
* • GLSL types: 'float' → float, 'color' → vec3, 'shader' → vec4, 'vector' → vec2
|
|
53
53
|
*
|
|
54
54
|
* @example
|
|
55
55
|
* const ripple = new ShaderScript({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShaderScript.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/ShaderScript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAK9D;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,EAAE,OAAO,CAAC,CAAA;AAEhF,oDAAoD;AACpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC,CAAA;AAEtF,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAG,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,YAAY,CAAC,CAAA;IAExD,2CAA2C;IAC3C,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAE1B;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAA;IAEZ;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAID;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,YAAa,SAAQ,WAAW;IAC3C,IAAI,QAAQ,WAA4B;IACxC,MAAM,CAAC,mBAAmB,UAAO;IAEjC,IAAI,QAAQ,IAAI,YAAY,CAQ3B;IAED,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+E;IACvG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;gBAE/C,MAAM,EAAE,kBAAkB;IAmCtC,eAAe;IACf,gBAAgB;IAEhB,mDAAmD;IACnD,WAAW,IAAI,MAAM;IAErB;;;;;;OAMG;IACH,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;IAkCxC,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"ShaderScript.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/ShaderScript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAK9D;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,EAAE,OAAO,CAAC,CAAA;AAEhF,oDAAoD;AACpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC,CAAA;AAEtF,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAG,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,YAAY,CAAC,CAAA;IAExD,2CAA2C;IAC3C,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAE1B;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAA;IAEZ;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAID;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,YAAa,SAAQ,WAAW;IAC3C,IAAI,QAAQ,WAA4B;IACxC,MAAM,CAAC,mBAAmB,UAAO;IAEjC,IAAI,QAAQ,IAAI,YAAY,CAQ3B;IAED,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+E;IACvG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;gBAE/C,MAAM,EAAE,kBAAkB;IAmCtC,eAAe;IACf,gBAAgB;IAEhB,mDAAmD;IACnD,WAAW,IAAI,MAAM;IAErB;;;;;;OAMG;IACH,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;IAkCxC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,aAAa;CAMtB"}
|
|
@@ -10,7 +10,7 @@ import { assertGlslIdentifier } from '../../core/glslIdentifier.js';
|
|
|
10
10
|
* Inside the GLSL body:
|
|
11
11
|
* • Input sockets are available as local variables with the exact name you declared.
|
|
12
12
|
* • Output sockets must be assigned by name before the block ends.
|
|
13
|
-
* • GLSL types: 'float' → float, 'color'
|
|
13
|
+
* • GLSL types: 'float' → float, 'color' → vec3, 'shader' → vec4, 'vector' → vec2
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* const ripple = new ShaderScript({
|
|
@@ -111,14 +111,18 @@ export class ShaderScript extends ProcessNode {
|
|
|
111
111
|
return 'float';
|
|
112
112
|
if (type === 'vector')
|
|
113
113
|
return 'vec2';
|
|
114
|
-
|
|
114
|
+
if (type === 'shader')
|
|
115
|
+
return 'vec4';
|
|
116
|
+
return 'vec3'; // 'color'
|
|
115
117
|
}
|
|
116
118
|
_declGlslType(type) {
|
|
117
119
|
if (type === 'float')
|
|
118
120
|
return 'float';
|
|
119
121
|
if (type === 'vector')
|
|
120
122
|
return 'vec2';
|
|
121
|
-
|
|
123
|
+
if (type === 'shader')
|
|
124
|
+
return 'vec4';
|
|
125
|
+
return 'vec3'; // 'color'
|
|
122
126
|
}
|
|
123
127
|
}
|
|
124
128
|
ShaderScript.instanceSpecificDef = true; // every script is unique — no dedup
|
|
@@ -25,8 +25,8 @@ export class ShaderToRGB extends ProcessNode {
|
|
|
25
25
|
const cv = ctx.outputVar(this, 'Color');
|
|
26
26
|
const av = ctx.outputVar(this, 'Alpha');
|
|
27
27
|
return [
|
|
28
|
-
`vec3 ${cv} = ${shader};`,
|
|
29
|
-
`float ${av} =
|
|
28
|
+
`vec3 ${cv} = (${shader}).rgb;`,
|
|
29
|
+
`float ${av} = (${shader}).a;`,
|
|
30
30
|
].join('\n ');
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -30,7 +30,7 @@ export class SheenBSDF extends ProcessNode {
|
|
|
30
30
|
const normal = this._inputs.normal.isConnected()
|
|
31
31
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
32
32
|
: 'normalize(vNormal)';
|
|
33
|
-
return `
|
|
33
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_sheenBSDF(${color}, ${roughness}, ${normal}), 1.0);`;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
SheenBSDF.instanceSpecificDef = false;
|
|
@@ -32,7 +32,7 @@ export class SpecularBSDF extends ProcessNode {
|
|
|
32
32
|
const normal = this._inputs.normal.isConnected()
|
|
33
33
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
34
34
|
: 'normalize(vNormal)';
|
|
35
|
-
return `
|
|
35
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_specularBSDF(${base}, ${spec}, ${roughness}, ${normal}), 1.0);`;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
SpecularBSDF.instanceSpecificDef = false;
|
|
@@ -32,7 +32,7 @@ export class SubsurfaceScattering extends ProcessNode {
|
|
|
32
32
|
const normal = this._inputs.normal.isConnected()
|
|
33
33
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
34
34
|
: 'normalize(vNormal)';
|
|
35
|
-
return `
|
|
35
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_sss(${color}, ${scale}, vec3(${r.toFixed(4)}, ${g.toFixed(4)}, ${b.toFixed(4)}), ${normal}), 1.0);`;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
SubsurfaceScattering.instanceSpecificDef = false;
|
|
@@ -31,7 +31,7 @@ export class ToonBSDF extends ProcessNode {
|
|
|
31
31
|
const normal = this._inputs.normal.isConnected()
|
|
32
32
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
33
33
|
: 'normalize(vNormal)';
|
|
34
|
-
return `
|
|
34
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_toonBSDF(${color}, ${size}, ${smoothWidth}, ${normal}), 1.0);`;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
ToonBSDF.instanceSpecificDef = false;
|
|
@@ -27,7 +27,7 @@ export class TranslucentBSDF extends ProcessNode {
|
|
|
27
27
|
const normal = this._inputs.normal.isConnected()
|
|
28
28
|
? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
|
|
29
29
|
: 'normalize(vNormal)';
|
|
30
|
-
return `
|
|
30
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(_st_translucentBSDF(${color}, ${normal}), 1.0);`;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
TranslucentBSDF.instanceSpecificDef = false;
|
|
@@ -26,7 +26,7 @@ export class VolumeAbsorption extends ProcessNode {
|
|
|
26
26
|
compileCall(ctx) {
|
|
27
27
|
const color = ctx.resolveInput(this._inputs.color);
|
|
28
28
|
const density = ctx.resolveInput(this._inputs.density);
|
|
29
|
-
return `
|
|
29
|
+
return `vec4 ${ctx.outputVar(this, 'Volume')} = vec4(_st_volumeAbsorption(${color}, ${density}), 1.0);`;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
VolumeAbsorption.instanceSpecificDef = false;
|
|
@@ -28,7 +28,7 @@ export class VolumeScatter extends ProcessNode {
|
|
|
28
28
|
const color = ctx.resolveInput(this._inputs.color);
|
|
29
29
|
const density = ctx.resolveInput(this._inputs.density);
|
|
30
30
|
const anisotropy = ctx.resolveInput(this._inputs.anisotropy);
|
|
31
|
-
return `
|
|
31
|
+
return `vec4 ${ctx.outputVar(this, 'Volume')} = vec4(_st_volumeScatter(${color}, ${density}, ${anisotropy}), 1.0);`;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
VolumeScatter.instanceSpecificDef = false;
|
|
@@ -50,7 +50,7 @@ export class RayPortal extends ProcessNode {
|
|
|
50
50
|
const blend = Number.isFinite(rawBlend) ? Math.min(Math.max(rawBlend, 0.0), 1.0).toFixed(4) : '1.0000';
|
|
51
51
|
// Rasterizer passthrough: BSDF = color * blend
|
|
52
52
|
// Portal Transform is intentionally unused in this mode.
|
|
53
|
-
return `
|
|
53
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(${color} * ${blend}, 1.0);`;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
RayPortal.instanceSpecificDef = false;
|