@triforge/shader-core 0.2.1 → 0.4.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 +196 -39
- 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 +23 -0
- package/dist/core/SocketType.d.ts +1 -1
- package/dist/core/SocketType.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/nodes/output/MaterialOutput.js +2 -2
- package/dist/nodes/process/AddShader.js +4 -4
- package/dist/nodes/process/Bump.d.ts +25 -2
- package/dist/nodes/process/Bump.d.ts.map +1 -1
- package/dist/nodes/process/Bump.js +113 -32
- package/dist/nodes/process/DiffuseBSDF.js +8 -8
- package/dist/nodes/process/Emission.js +4 -4
- package/dist/nodes/process/GlassBSDF.js +14 -14
- package/dist/nodes/process/GlossyBSDF.js +15 -15
- package/dist/nodes/process/MixShader.js +4 -4
- 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 +55 -40
- package/dist/nodes/process/PrincipledHair.js +71 -71
- package/dist/nodes/process/PrincipledVolume.js +22 -22
- package/dist/nodes/process/RefractionBSDF.js +8 -8
- 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 +13 -13
- package/dist/nodes/process/SpecularBSDF.js +16 -16
- package/dist/nodes/process/SubsurfaceScattering.js +8 -8
- package/dist/nodes/process/ToonBSDF.js +7 -7
- package/dist/nodes/process/TranslucentBSDF.js +6 -6
- package/dist/nodes/process/TransparentBSDF.d.ts +26 -0
- package/dist/nodes/process/TransparentBSDF.d.ts.map +1 -0
- package/dist/nodes/process/TransparentBSDF.js +29 -0
- package/dist/nodes/process/VolumeAbsorption.js +4 -4
- package/dist/nodes/process/VolumeScatter.js +8 -8
- package/dist/nodes/shader/RayPortal.js +1 -1
- package/package.json +1 -1
|
@@ -25,51 +25,66 @@ 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;
|
|
36
|
-
PrincipledBSDF.glslFunction = `
|
|
37
|
-
// Set these on material.uniforms after compile()
|
|
38
|
-
#ifndef _ST_HAIR_LIGHT_UNIFORMS
|
|
39
|
-
#define _ST_HAIR_LIGHT_UNIFORMS
|
|
40
|
-
uniform vec3 uSunDirection;
|
|
41
|
-
uniform vec3 uSunColor;
|
|
42
|
-
uniform vec3 uAmbientColor;
|
|
43
|
-
#endif
|
|
44
|
-
|
|
45
|
-
vec3 _st_schlick(vec3 F0, float c) {
|
|
46
|
-
return F0 + (1.0 - F0) * pow(clamp(1.0 - c, 0.0, 1.0), 5.0);
|
|
47
|
-
}
|
|
48
|
-
float _st_ggx(float NdotH, float r) {
|
|
49
|
-
float a = r * r, a2 = a * a;
|
|
50
|
-
float d = (NdotH * NdotH) * (a2 - 1.0) + 1.0;
|
|
51
|
-
return a2 / max(3.14159 * d * d, 1e-7);
|
|
52
|
-
}
|
|
53
|
-
float _st_geo(float NdotX, float r) {
|
|
54
|
-
float k = (r + 1.0) * (r + 1.0) / 8.0;
|
|
55
|
-
return NdotX / max(NdotX * (1.0 - k) + k, 1e-7);
|
|
56
|
-
}
|
|
57
|
-
vec3 _st_principledBSDF(vec3 base, float metallic, float roughness, float ior,
|
|
58
|
-
vec3 V = normalize(cameraPosition - vPosition);
|
|
59
|
-
vec3 L = normalize(uSunDirection);
|
|
60
|
-
vec3 H = normalize(L + V);
|
|
61
|
-
float r = max(roughness, 0.04);
|
|
62
|
-
float NdotL = max(dot(N, L), 0.0);
|
|
63
|
-
float NdotV = max(dot(N, V), 1e-4);
|
|
64
|
-
float NdotH = max(dot(N, H), 0.0);
|
|
65
|
-
float HdotV = max(dot(H, V), 0.0);
|
|
66
|
-
float f0s = pow((1.0 - ior) / (1.0 + ior), 2.0);
|
|
67
|
-
vec3 F0 = mix(vec3(f0s), base, metallic);
|
|
68
|
-
vec3 F = _st_schlick(F0, HdotV);
|
|
69
|
-
float D = _st_ggx(NdotH, r);
|
|
70
|
-
float G = _st_geo(NdotL, r) * _st_geo(NdotV, r);
|
|
71
|
-
vec3 spec = (D * G * F) / max(4.0 * NdotV * NdotL, 1e-7);
|
|
72
|
-
vec3 kD = (1.0 - F) * (1.0 - metallic);
|
|
73
|
-
vec3 ambient = uAmbientColor * base;
|
|
74
|
-
return ambient + (kD * base / 3.14159 + spec * uSunColor) * NdotL;
|
|
51
|
+
PrincipledBSDF.glslFunction = `
|
|
52
|
+
// Set these on material.uniforms after compile()
|
|
53
|
+
#ifndef _ST_HAIR_LIGHT_UNIFORMS
|
|
54
|
+
#define _ST_HAIR_LIGHT_UNIFORMS
|
|
55
|
+
uniform vec3 uSunDirection;
|
|
56
|
+
uniform vec3 uSunColor;
|
|
57
|
+
uniform vec3 uAmbientColor;
|
|
58
|
+
#endif
|
|
59
|
+
|
|
60
|
+
vec3 _st_schlick(vec3 F0, float c) {
|
|
61
|
+
return F0 + (1.0 - F0) * pow(clamp(1.0 - c, 0.0, 1.0), 5.0);
|
|
62
|
+
}
|
|
63
|
+
float _st_ggx(float NdotH, float r) {
|
|
64
|
+
float a = r * r, a2 = a * a;
|
|
65
|
+
float d = (NdotH * NdotH) * (a2 - 1.0) + 1.0;
|
|
66
|
+
return a2 / max(3.14159 * d * d, 1e-7);
|
|
67
|
+
}
|
|
68
|
+
float _st_geo(float NdotX, float r) {
|
|
69
|
+
float k = (r + 1.0) * (r + 1.0) / 8.0;
|
|
70
|
+
return NdotX / max(NdotX * (1.0 - k) + k, 1e-7);
|
|
71
|
+
}
|
|
72
|
+
vec3 _st_principledBSDF(vec3 base, float metallic, float roughness, float ior, vec3 N) {
|
|
73
|
+
vec3 V = normalize(cameraPosition - vPosition);
|
|
74
|
+
vec3 L = normalize(uSunDirection);
|
|
75
|
+
vec3 H = normalize(L + V);
|
|
76
|
+
float r = max(roughness, 0.04);
|
|
77
|
+
float NdotL = max(dot(N, L), 0.0);
|
|
78
|
+
float NdotV = max(dot(N, V), 1e-4);
|
|
79
|
+
float NdotH = max(dot(N, H), 0.0);
|
|
80
|
+
float HdotV = max(dot(H, V), 0.0);
|
|
81
|
+
float f0s = pow((1.0 - ior) / (1.0 + ior), 2.0);
|
|
82
|
+
vec3 F0 = mix(vec3(f0s), base, metallic);
|
|
83
|
+
vec3 F = _st_schlick(F0, HdotV);
|
|
84
|
+
float D = _st_ggx(NdotH, r);
|
|
85
|
+
float G = _st_geo(NdotL, r) * _st_geo(NdotV, r);
|
|
86
|
+
vec3 spec = (D * G * F) / max(4.0 * NdotV * NdotL, 1e-7);
|
|
87
|
+
vec3 kD = (1.0 - F) * (1.0 - metallic);
|
|
88
|
+
vec3 ambient = uAmbientColor * base;
|
|
89
|
+
return ambient + (kD * base / 3.14159 + spec * uSunColor) * NdotL;
|
|
75
90
|
}`;
|
|
@@ -59,79 +59,79 @@ 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;
|
|
66
66
|
// Light uniforms guarded by a #define so they survive alongside PrincipledBSDF in the same graph.
|
|
67
|
-
PrincipledHair.glslFunction = `
|
|
68
|
-
#ifndef _ST_HAIR_LIGHT_UNIFORMS
|
|
69
|
-
#define _ST_HAIR_LIGHT_UNIFORMS
|
|
70
|
-
uniform vec3 uSunDirection;
|
|
71
|
-
uniform vec3 uSunColor;
|
|
72
|
-
uniform vec3 uAmbientColor;
|
|
73
|
-
#endif
|
|
74
|
-
|
|
75
|
-
float _st_hairHash(float n) {
|
|
76
|
-
return fract(sin(n * 127.1 + 311.7) * 43758.5453);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Kajiya-Kay dual-lobe hair BSDF.
|
|
80
|
-
// T = strand tangent (unit, world space)
|
|
81
|
-
// R = primary specular exponent = 1 / (roughness^2)
|
|
82
|
-
// R2 = secondary specular exponent = 1 / (radialRoughness^2)
|
|
83
|
-
vec3 _st_principledHair(
|
|
84
|
-
vec3 color,
|
|
85
|
-
float roughness,
|
|
86
|
-
float radialRoughness,
|
|
87
|
-
float coat,
|
|
88
|
-
float ior,
|
|
89
|
-
float offset,
|
|
90
|
-
float randomColor,
|
|
91
|
-
float randomRoughness,
|
|
92
|
-
float rnd,
|
|
93
|
-
vec3 T
|
|
94
|
-
) {
|
|
95
|
-
// Per-strand variation
|
|
96
|
-
float rc = _st_hairHash(rnd * 1.3731 + 0.1);
|
|
97
|
-
float rr = _st_hairHash(rnd * 2.7183 + 0.2);
|
|
98
|
-
color = mix(color, color * (0.6 + 0.8 * rc), randomColor);
|
|
99
|
-
roughness = clamp(roughness + (rr - 0.5) * randomRoughness * 0.5, 0.02, 1.0);
|
|
100
|
-
|
|
101
|
-
vec3 V = normalize(cameraPosition - vPosition);
|
|
102
|
-
vec3 L = normalize(uSunDirection);
|
|
103
|
-
vec3 H = normalize(L + V);
|
|
104
|
-
vec3 N = normalize(vNormal);
|
|
105
|
-
|
|
106
|
-
// Kajiya-Kay diffuse: sin(angle T, L)
|
|
107
|
-
float cosT = dot(T, L);
|
|
108
|
-
float sinT = sqrt(max(1.0 - cosT * cosT, 0.0));
|
|
109
|
-
float diff = sinT * max(dot(N, L) * 0.5 + 0.5, 0.0); // wrap diffuse
|
|
110
|
-
|
|
111
|
-
// R lobe — primary specular, shifted by +offset along normal
|
|
112
|
-
float f0 = pow(clamp((1.0 - ior) / (1.0 + ior), 0.0, 1.0), 2.0);
|
|
113
|
-
vec3 T1 = normalize(T + offset * N);
|
|
114
|
-
float cosTH1 = dot(T1, H);
|
|
115
|
-
float sinTH1 = sqrt(max(1.0 - cosTH1 * cosTH1, 0.0));
|
|
116
|
-
float exp1 = max(1.0 / max(roughness * roughness, 0.001), 1.0);
|
|
117
|
-
float spec1 = pow(sinTH1, exp1);
|
|
118
|
-
vec3 F1 = vec3(f0) + (vec3(1.0) - vec3(f0)) * pow(1.0 - max(dot(H, V), 0.0), 5.0);
|
|
119
|
-
|
|
120
|
-
// TRT lobe — secondary specular, shifted by -2*offset, colored
|
|
121
|
-
vec3 T2 = normalize(T - 2.0 * offset * N);
|
|
122
|
-
float cosTH2 = dot(T2, H);
|
|
123
|
-
float sinTH2 = sqrt(max(1.0 - cosTH2 * cosTH2, 0.0));
|
|
124
|
-
float rr2 = clamp(radialRoughness, 0.02, 1.0);
|
|
125
|
-
float exp2 = max(1.0 / max(rr2 * rr2, 0.001), 1.0);
|
|
126
|
-
float spec2 = pow(sinTH2, exp2) * 0.25;
|
|
127
|
-
|
|
128
|
-
// Coat gloss
|
|
129
|
-
float cosTHc = dot(T, H);
|
|
130
|
-
float sinTHc = sqrt(max(1.0 - cosTHc * cosTHc, 0.0));
|
|
131
|
-
float coatSpec = pow(sinTHc, 128.0) * coat;
|
|
132
|
-
|
|
133
|
-
vec3 diffuse = color * (uSunColor * diff + uAmbientColor);
|
|
134
|
-
vec3 specular = uSunColor * (F1 * spec1 + vec3(coatSpec)) + color * uSunColor * spec2;
|
|
135
|
-
|
|
136
|
-
return diffuse + specular;
|
|
67
|
+
PrincipledHair.glslFunction = `
|
|
68
|
+
#ifndef _ST_HAIR_LIGHT_UNIFORMS
|
|
69
|
+
#define _ST_HAIR_LIGHT_UNIFORMS
|
|
70
|
+
uniform vec3 uSunDirection;
|
|
71
|
+
uniform vec3 uSunColor;
|
|
72
|
+
uniform vec3 uAmbientColor;
|
|
73
|
+
#endif
|
|
74
|
+
|
|
75
|
+
float _st_hairHash(float n) {
|
|
76
|
+
return fract(sin(n * 127.1 + 311.7) * 43758.5453);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Kajiya-Kay dual-lobe hair BSDF.
|
|
80
|
+
// T = strand tangent (unit, world space)
|
|
81
|
+
// R = primary specular exponent = 1 / (roughness^2)
|
|
82
|
+
// R2 = secondary specular exponent = 1 / (radialRoughness^2)
|
|
83
|
+
vec3 _st_principledHair(
|
|
84
|
+
vec3 color,
|
|
85
|
+
float roughness,
|
|
86
|
+
float radialRoughness,
|
|
87
|
+
float coat,
|
|
88
|
+
float ior,
|
|
89
|
+
float offset,
|
|
90
|
+
float randomColor,
|
|
91
|
+
float randomRoughness,
|
|
92
|
+
float rnd,
|
|
93
|
+
vec3 T
|
|
94
|
+
) {
|
|
95
|
+
// Per-strand variation
|
|
96
|
+
float rc = _st_hairHash(rnd * 1.3731 + 0.1);
|
|
97
|
+
float rr = _st_hairHash(rnd * 2.7183 + 0.2);
|
|
98
|
+
color = mix(color, color * (0.6 + 0.8 * rc), randomColor);
|
|
99
|
+
roughness = clamp(roughness + (rr - 0.5) * randomRoughness * 0.5, 0.02, 1.0);
|
|
100
|
+
|
|
101
|
+
vec3 V = normalize(cameraPosition - vPosition);
|
|
102
|
+
vec3 L = normalize(uSunDirection);
|
|
103
|
+
vec3 H = normalize(L + V);
|
|
104
|
+
vec3 N = normalize(vNormal);
|
|
105
|
+
|
|
106
|
+
// Kajiya-Kay diffuse: sin(angle T, L)
|
|
107
|
+
float cosT = dot(T, L);
|
|
108
|
+
float sinT = sqrt(max(1.0 - cosT * cosT, 0.0));
|
|
109
|
+
float diff = sinT * max(dot(N, L) * 0.5 + 0.5, 0.0); // wrap diffuse
|
|
110
|
+
|
|
111
|
+
// R lobe — primary specular, shifted by +offset along normal
|
|
112
|
+
float f0 = pow(clamp((1.0 - ior) / (1.0 + ior), 0.0, 1.0), 2.0);
|
|
113
|
+
vec3 T1 = normalize(T + offset * N);
|
|
114
|
+
float cosTH1 = dot(T1, H);
|
|
115
|
+
float sinTH1 = sqrt(max(1.0 - cosTH1 * cosTH1, 0.0));
|
|
116
|
+
float exp1 = max(1.0 / max(roughness * roughness, 0.001), 1.0);
|
|
117
|
+
float spec1 = pow(sinTH1, exp1);
|
|
118
|
+
vec3 F1 = vec3(f0) + (vec3(1.0) - vec3(f0)) * pow(1.0 - max(dot(H, V), 0.0), 5.0);
|
|
119
|
+
|
|
120
|
+
// TRT lobe — secondary specular, shifted by -2*offset, colored
|
|
121
|
+
vec3 T2 = normalize(T - 2.0 * offset * N);
|
|
122
|
+
float cosTH2 = dot(T2, H);
|
|
123
|
+
float sinTH2 = sqrt(max(1.0 - cosTH2 * cosTH2, 0.0));
|
|
124
|
+
float rr2 = clamp(radialRoughness, 0.02, 1.0);
|
|
125
|
+
float exp2 = max(1.0 / max(rr2 * rr2, 0.001), 1.0);
|
|
126
|
+
float spec2 = pow(sinTH2, exp2) * 0.25;
|
|
127
|
+
|
|
128
|
+
// Coat gloss
|
|
129
|
+
float cosTHc = dot(T, H);
|
|
130
|
+
float sinTHc = sqrt(max(1.0 - cosTHc * cosTHc, 0.0));
|
|
131
|
+
float coatSpec = pow(sinTHc, 128.0) * coat;
|
|
132
|
+
|
|
133
|
+
vec3 diffuse = color * (uSunColor * diff + uAmbientColor);
|
|
134
|
+
vec3 specular = uSunColor * (F1 * spec1 + vec3(coatSpec)) + color * uSunColor * spec2;
|
|
135
|
+
|
|
136
|
+
return diffuse + specular;
|
|
137
137
|
}`;
|
|
@@ -39,29 +39,29 @@ 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;
|
|
46
|
-
PrincipledVolume.glslFunction = `
|
|
47
|
-
vec3 _st_principledVolume(
|
|
48
|
-
vec3 scatterColor, float density,
|
|
49
|
-
float anisotropy, vec3 absorptionColor,
|
|
50
|
-
vec3 emissionColor, float emissionStrength,
|
|
51
|
-
float blackbodyIntensity, float temperature
|
|
52
|
-
) {
|
|
53
|
-
float g = clamp(anisotropy, -0.9999, 0.9999);
|
|
54
|
-
float g2 = g * g;
|
|
55
|
-
float phase = (1.0 - g2) / pow(1.0 + g2, 1.5);
|
|
56
|
-
|
|
57
|
-
vec3 scatter = scatterColor * density * phase;
|
|
58
|
-
vec3 absorption = absorptionColor * density;
|
|
59
|
-
vec3 emission = emissionColor * emissionStrength;
|
|
60
|
-
|
|
61
|
-
// Simplified blackbody tint: blend toward hot white at high temperature
|
|
62
|
-
float tNorm = clamp((temperature - 800.0) / 4200.0, 0.0, 1.0);
|
|
63
|
-
vec3 bb = mix(vec3(1.0, 0.2, 0.0), vec3(1.0, 0.95, 0.8), tNorm);
|
|
64
|
-
emission += bb * blackbodyIntensity * density;
|
|
65
|
-
|
|
66
|
-
return scatter + emission - absorption * 0.5;
|
|
46
|
+
PrincipledVolume.glslFunction = `
|
|
47
|
+
vec3 _st_principledVolume(
|
|
48
|
+
vec3 scatterColor, float density,
|
|
49
|
+
float anisotropy, vec3 absorptionColor,
|
|
50
|
+
vec3 emissionColor, float emissionStrength,
|
|
51
|
+
float blackbodyIntensity, float temperature
|
|
52
|
+
) {
|
|
53
|
+
float g = clamp(anisotropy, -0.9999, 0.9999);
|
|
54
|
+
float g2 = g * g;
|
|
55
|
+
float phase = (1.0 - g2) / pow(1.0 + g2, 1.5);
|
|
56
|
+
|
|
57
|
+
vec3 scatter = scatterColor * density * phase;
|
|
58
|
+
vec3 absorption = absorptionColor * density;
|
|
59
|
+
vec3 emission = emissionColor * emissionStrength;
|
|
60
|
+
|
|
61
|
+
// Simplified blackbody tint: blend toward hot white at high temperature
|
|
62
|
+
float tNorm = clamp((temperature - 800.0) / 4200.0, 0.0, 1.0);
|
|
63
|
+
vec3 bb = mix(vec3(1.0, 0.2, 0.0), vec3(1.0, 0.95, 0.8), tNorm);
|
|
64
|
+
emission += bb * blackbodyIntensity * density;
|
|
65
|
+
|
|
66
|
+
return scatter + emission - absorption * 0.5;
|
|
67
67
|
}`;
|
|
@@ -32,15 +32,15 @@ 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;
|
|
39
|
-
RefractionBSDF.glslFunction = `
|
|
40
|
-
vec3 _st_refractionBSDF(vec3 color, float roughness, float ior, vec3 N) {
|
|
41
|
-
vec3 V = normalize(cameraPosition - vPosition);
|
|
42
|
-
vec3 refDir = refract(-V, N, 1.0 / ior);
|
|
43
|
-
float fresnel = pow(1.0 - max(dot(V, N), 0.0), 5.0);
|
|
44
|
-
vec3 refColor = color * (1.0 - fresnel) * (1.0 - roughness * 0.5);
|
|
45
|
-
return refColor;
|
|
39
|
+
RefractionBSDF.glslFunction = `
|
|
40
|
+
vec3 _st_refractionBSDF(vec3 color, float roughness, float ior, vec3 N) {
|
|
41
|
+
vec3 V = normalize(cameraPosition - vPosition);
|
|
42
|
+
vec3 refDir = refract(-V, N, 1.0 / ior);
|
|
43
|
+
float fresnel = pow(1.0 - max(dot(V, N), 0.0), 5.0);
|
|
44
|
+
vec3 refColor = color * (1.0 - fresnel) * (1.0 - roughness * 0.5);
|
|
45
|
+
return refColor;
|
|
46
46
|
}`;
|
|
@@ -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,20 +30,20 @@ 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;
|
|
37
|
-
SheenBSDF.glslFunction = `
|
|
38
|
-
vec3 _st_sheenBSDF(vec3 color, float roughness, vec3 N) {
|
|
39
|
-
vec3 V = normalize(cameraPosition - vPosition);
|
|
40
|
-
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
41
|
-
vec3 H = normalize(L + V);
|
|
42
|
-
float NdotL = max(dot(N, L), 0.0);
|
|
43
|
-
float NdotV = max(dot(N, V), 0.0001);
|
|
44
|
-
float NdotH = max(dot(N, H), 0.0);
|
|
45
|
-
float sinThetaH = sqrt(max(1.0 - NdotH * NdotH, 0.0));
|
|
46
|
-
float r2 = roughness * roughness;
|
|
47
|
-
float sheen = (2.0 + 1.0 / r2) * pow(sinThetaH, 1.0 / r2) / (2.0 * 3.14159);
|
|
48
|
-
return color * sheen * NdotL / max(NdotL + NdotV - NdotL * NdotV, 0.0001) + color * 0.03;
|
|
37
|
+
SheenBSDF.glslFunction = `
|
|
38
|
+
vec3 _st_sheenBSDF(vec3 color, float roughness, vec3 N) {
|
|
39
|
+
vec3 V = normalize(cameraPosition - vPosition);
|
|
40
|
+
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
41
|
+
vec3 H = normalize(L + V);
|
|
42
|
+
float NdotL = max(dot(N, L), 0.0);
|
|
43
|
+
float NdotV = max(dot(N, V), 0.0001);
|
|
44
|
+
float NdotH = max(dot(N, H), 0.0);
|
|
45
|
+
float sinThetaH = sqrt(max(1.0 - NdotH * NdotH, 0.0));
|
|
46
|
+
float r2 = roughness * roughness;
|
|
47
|
+
float sheen = (2.0 + 1.0 / r2) * pow(sinThetaH, 1.0 / r2) / (2.0 * 3.14159);
|
|
48
|
+
return color * sheen * NdotL / max(NdotL + NdotV - NdotL * NdotV, 0.0001) + color * 0.03;
|
|
49
49
|
}`;
|
|
@@ -32,23 +32,23 @@ 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;
|
|
39
|
-
SpecularBSDF.glslFunction = `
|
|
40
|
-
vec3 _st_specularBSDF(vec3 base, vec3 spec, float roughness, vec3 N) {
|
|
41
|
-
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
42
|
-
vec3 V = normalize(cameraPosition - vPosition);
|
|
43
|
-
vec3 H = normalize(L + V);
|
|
44
|
-
float NdotL = max(dot(N, L), 0.0);
|
|
45
|
-
float NdotH = max(dot(N, H), 0.0);
|
|
46
|
-
float NdotV = max(dot(N, V), 0.0001);
|
|
47
|
-
float a2 = pow(roughness, 4.0);
|
|
48
|
-
float D = a2 / max(3.14159 * pow(NdotH * NdotH * (a2 - 1.0) + 1.0, 2.0), 0.0001);
|
|
49
|
-
float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
|
|
50
|
-
float G = (NdotL / (NdotL * (1.0 - k) + k)) * (NdotV / (NdotV * (1.0 - k) + k));
|
|
51
|
-
vec3 F = spec + (1.0 - spec) * pow(1.0 - max(dot(H, V), 0.0), 5.0);
|
|
52
|
-
vec3 specColor = D * G * F / max(4.0 * NdotL * NdotV, 0.0001);
|
|
53
|
-
return (base / 3.14159 + specColor) * NdotL + base * 0.04;
|
|
39
|
+
SpecularBSDF.glslFunction = `
|
|
40
|
+
vec3 _st_specularBSDF(vec3 base, vec3 spec, float roughness, vec3 N) {
|
|
41
|
+
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
42
|
+
vec3 V = normalize(cameraPosition - vPosition);
|
|
43
|
+
vec3 H = normalize(L + V);
|
|
44
|
+
float NdotL = max(dot(N, L), 0.0);
|
|
45
|
+
float NdotH = max(dot(N, H), 0.0);
|
|
46
|
+
float NdotV = max(dot(N, V), 0.0001);
|
|
47
|
+
float a2 = pow(roughness, 4.0);
|
|
48
|
+
float D = a2 / max(3.14159 * pow(NdotH * NdotH * (a2 - 1.0) + 1.0, 2.0), 0.0001);
|
|
49
|
+
float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
|
|
50
|
+
float G = (NdotL / (NdotL * (1.0 - k) + k)) * (NdotV / (NdotV * (1.0 - k) + k));
|
|
51
|
+
vec3 F = spec + (1.0 - spec) * pow(1.0 - max(dot(H, V), 0.0), 5.0);
|
|
52
|
+
vec3 specColor = D * G * F / max(4.0 * NdotL * NdotV, 0.0001);
|
|
53
|
+
return (base / 3.14159 + specColor) * NdotL + base * 0.04;
|
|
54
54
|
}`;
|
|
@@ -32,15 +32,15 @@ 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;
|
|
39
|
-
SubsurfaceScattering.glslFunction = `
|
|
40
|
-
vec3 _st_sss(vec3 color, float scale, vec3 radius, vec3 N) {
|
|
41
|
-
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
42
|
-
float wrap = max(dot(N, L) * 0.5 + 0.5, 0.0);
|
|
43
|
-
vec3 scatter = color * radius * wrap * scale;
|
|
44
|
-
float back = max(-dot(N, L), 0.0) * scale * 0.3;
|
|
45
|
-
return color * (0.04 + wrap * 0.5) + scatter + color * back;
|
|
39
|
+
SubsurfaceScattering.glslFunction = `
|
|
40
|
+
vec3 _st_sss(vec3 color, float scale, vec3 radius, vec3 N) {
|
|
41
|
+
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
42
|
+
float wrap = max(dot(N, L) * 0.5 + 0.5, 0.0);
|
|
43
|
+
vec3 scatter = color * radius * wrap * scale;
|
|
44
|
+
float back = max(-dot(N, L), 0.0) * scale * 0.3;
|
|
45
|
+
return color * (0.04 + wrap * 0.5) + scatter + color * back;
|
|
46
46
|
}`;
|
|
@@ -31,14 +31,14 @@ 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;
|
|
38
|
-
ToonBSDF.glslFunction = `
|
|
39
|
-
vec3 _st_toonBSDF(vec3 color, float size, float smoothWidth, vec3 N) {
|
|
40
|
-
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
41
|
-
float NdotL = dot(N, L) * 0.5 + 0.5;
|
|
42
|
-
float band = smoothstep(size - smoothWidth, size + smoothWidth, NdotL);
|
|
43
|
-
return color * band + color * 0.1;
|
|
38
|
+
ToonBSDF.glslFunction = `
|
|
39
|
+
vec3 _st_toonBSDF(vec3 color, float size, float smoothWidth, vec3 N) {
|
|
40
|
+
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
41
|
+
float NdotL = dot(N, L) * 0.5 + 0.5;
|
|
42
|
+
float band = smoothstep(size - smoothWidth, size + smoothWidth, NdotL);
|
|
43
|
+
return color * band + color * 0.1;
|
|
44
44
|
}`;
|
|
@@ -27,13 +27,13 @@ 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;
|
|
34
|
-
TranslucentBSDF.glslFunction = `
|
|
35
|
-
vec3 _st_translucentBSDF(vec3 color, vec3 N) {
|
|
36
|
-
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
37
|
-
float backDot = max(dot(-N, L), 0.0);
|
|
38
|
-
return color * backDot / 3.14159265 + color * 0.02;
|
|
34
|
+
TranslucentBSDF.glslFunction = `
|
|
35
|
+
vec3 _st_translucentBSDF(vec3 color, vec3 N) {
|
|
36
|
+
vec3 L = normalize(vec3(1.0, 2.0, 1.0));
|
|
37
|
+
float backDot = max(dot(-N, L), 0.0);
|
|
38
|
+
return color * backDot / 3.14159265 + color * 0.02;
|
|
39
39
|
}`;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
import type { NodeMetadata } from '../../core/ShaderNode.js';
|
|
3
|
+
import type { CompileContext } from '../../core/CompileContext.js';
|
|
4
|
+
/**
|
|
5
|
+
* Transparent BSDF — Blender "Transparent BSDF" node equivalent.
|
|
6
|
+
* Passes light through unfiltered — full transparency, colorless, no inputs.
|
|
7
|
+
* Combine with MixShader/AddShader to build cutout, fresnel-fade, or
|
|
8
|
+
* rim-light materials without a hand-written GLSL output node.
|
|
9
|
+
*
|
|
10
|
+
* Outputs: BSDF (shader) — always vec4(0.0, 0.0, 0.0, 0.0)
|
|
11
|
+
*/
|
|
12
|
+
export declare class TransparentBSDF extends ProcessNode {
|
|
13
|
+
get nodeType(): string;
|
|
14
|
+
static instanceSpecificDef: boolean;
|
|
15
|
+
get metadata(): NodeMetadata;
|
|
16
|
+
private readonly _inputs;
|
|
17
|
+
private readonly _outputs;
|
|
18
|
+
constructor();
|
|
19
|
+
getInputSockets(): Record<string, import("../../index.js").InputSocket<unknown>>;
|
|
20
|
+
getOutputSockets(): Record<string, import("../../index.js").OutputSocket>;
|
|
21
|
+
compileDefs(): string;
|
|
22
|
+
/** Always fully transparent — a constant, not a dynamic value, so this always requests transparent:true. */
|
|
23
|
+
wantsTransparency(): boolean;
|
|
24
|
+
compileCall(ctx: CompileContext): string;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=TransparentBSDF.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TransparentBSDF.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/TransparentBSDF.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;AAElE;;;;;;;GAOG;AACH,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,IAAI,QAAQ,WAA+B;IAC3C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;;IAQ5F,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,4GAA4G;IAC5G,iBAAiB,IAAI,OAAO;IAE5B,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAGzC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ProcessNode } from '../../core/ProcessNode.js';
|
|
2
|
+
/**
|
|
3
|
+
* Transparent BSDF — Blender "Transparent BSDF" node equivalent.
|
|
4
|
+
* Passes light through unfiltered — full transparency, colorless, no inputs.
|
|
5
|
+
* Combine with MixShader/AddShader to build cutout, fresnel-fade, or
|
|
6
|
+
* rim-light materials without a hand-written GLSL output node.
|
|
7
|
+
*
|
|
8
|
+
* Outputs: BSDF (shader) — always vec4(0.0, 0.0, 0.0, 0.0)
|
|
9
|
+
*/
|
|
10
|
+
export class TransparentBSDF extends ProcessNode {
|
|
11
|
+
get nodeType() { return 'TransparentBSDF'; }
|
|
12
|
+
get metadata() {
|
|
13
|
+
return { label: 'Transparent BSDF', category: 'Shader', color: '#336699', cost: 'low' };
|
|
14
|
+
}
|
|
15
|
+
constructor() {
|
|
16
|
+
super('TransparentBSDF');
|
|
17
|
+
this._inputs = this.createInputs({}, {});
|
|
18
|
+
this._outputs = this.createOutputs({ BSDF: 'shader' });
|
|
19
|
+
}
|
|
20
|
+
getInputSockets() { return this._inputs; }
|
|
21
|
+
getOutputSockets() { return this._outputs; }
|
|
22
|
+
compileDefs() { return ''; }
|
|
23
|
+
/** Always fully transparent — a constant, not a dynamic value, so this always requests transparent:true. */
|
|
24
|
+
wantsTransparency() { return true; }
|
|
25
|
+
compileCall(ctx) {
|
|
26
|
+
return `vec4 ${ctx.outputVar(this, 'BSDF')} = vec4(0.0, 0.0, 0.0, 0.0);`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
TransparentBSDF.instanceSpecificDef = false;
|
|
@@ -26,11 +26,11 @@ 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;
|
|
33
|
-
VolumeAbsorption.glslFunction = `
|
|
34
|
-
vec3 _st_volumeAbsorption(vec3 color, float density) {
|
|
35
|
-
return color * density;
|
|
33
|
+
VolumeAbsorption.glslFunction = `
|
|
34
|
+
vec3 _st_volumeAbsorption(vec3 color, float density) {
|
|
35
|
+
return color * density;
|
|
36
36
|
}`;
|