reze-engine 0.17.1 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/engine.d.ts +34 -0
  2. package/dist/engine.d.ts.map +1 -1
  3. package/dist/engine.js +258 -15
  4. package/dist/gpu-profile.d.ts +19 -0
  5. package/dist/gpu-profile.d.ts.map +1 -0
  6. package/dist/gpu-profile.js +120 -0
  7. package/dist/graph/compile.d.ts +34 -0
  8. package/dist/graph/compile.d.ts.map +1 -0
  9. package/dist/graph/compile.js +299 -0
  10. package/dist/graph/presets/body.d.ts +3 -0
  11. package/dist/graph/presets/body.d.ts.map +1 -0
  12. package/dist/graph/presets/body.js +100 -0
  13. package/dist/graph/presets/cloth_rough.d.ts +3 -0
  14. package/dist/graph/presets/cloth_rough.d.ts.map +1 -0
  15. package/dist/graph/presets/cloth_rough.js +61 -0
  16. package/dist/graph/presets/cloth_smooth.d.ts +3 -0
  17. package/dist/graph/presets/cloth_smooth.d.ts.map +1 -0
  18. package/dist/graph/presets/cloth_smooth.js +53 -0
  19. package/dist/graph/presets/default.d.ts +3 -0
  20. package/dist/graph/presets/default.d.ts.map +1 -0
  21. package/dist/graph/presets/default.js +20 -0
  22. package/dist/graph/presets/eye.d.ts +3 -0
  23. package/dist/graph/presets/eye.d.ts.map +1 -0
  24. package/dist/graph/presets/eye.js +30 -0
  25. package/dist/graph/presets/face.d.ts +3 -0
  26. package/dist/graph/presets/face.d.ts.map +1 -0
  27. package/dist/graph/presets/face.js +125 -0
  28. package/dist/graph/presets/hair.d.ts +3 -0
  29. package/dist/graph/presets/hair.d.ts.map +1 -0
  30. package/dist/graph/presets/hair.js +79 -0
  31. package/dist/graph/presets/metal.d.ts +3 -0
  32. package/dist/graph/presets/metal.d.ts.map +1 -0
  33. package/dist/graph/presets/metal.js +58 -0
  34. package/dist/graph/presets/stockings.d.ts +3 -0
  35. package/dist/graph/presets/stockings.d.ts.map +1 -0
  36. package/dist/graph/presets/stockings.js +54 -0
  37. package/dist/graph/registry.d.ts +28 -0
  38. package/dist/graph/registry.d.ts.map +1 -0
  39. package/dist/graph/registry.js +322 -0
  40. package/dist/graph/schema.d.ts +66 -0
  41. package/dist/graph/schema.d.ts.map +1 -0
  42. package/dist/graph/schema.js +6 -0
  43. package/dist/graph/slots.d.ts +14 -0
  44. package/dist/graph/slots.d.ts.map +1 -0
  45. package/dist/graph/slots.js +155 -0
  46. package/dist/index.d.ts +13 -1
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +11 -0
  49. package/dist/physics/profile.d.ts +18 -0
  50. package/dist/physics/profile.d.ts.map +1 -0
  51. package/dist/physics/profile.js +44 -0
  52. package/package.json +2 -1
  53. package/src/engine.ts +290 -15
  54. package/src/graph/compile.ts +342 -0
  55. package/src/graph/presets/body.ts +103 -0
  56. package/src/graph/presets/cloth_rough.ts +64 -0
  57. package/src/graph/presets/cloth_smooth.ts +56 -0
  58. package/src/graph/presets/default.ts +23 -0
  59. package/src/graph/presets/eye.ts +33 -0
  60. package/src/graph/presets/face.ts +136 -0
  61. package/src/graph/presets/hair.ts +82 -0
  62. package/src/graph/presets/metal.ts +61 -0
  63. package/src/graph/presets/stockings.ts +57 -0
  64. package/src/graph/registry.ts +351 -0
  65. package/src/graph/schema.ts +60 -0
  66. package/src/graph/slots.ts +178 -0
  67. package/src/index.ts +27 -0
  68. package/dist/physics-debug.d.ts +0 -30
  69. package/dist/physics-debug.d.ts.map +0 -1
  70. package/dist/physics-debug.js +0 -526
  71. package/dist/shaders/passes/physics-debug.d.ts +0 -2
  72. package/dist/shaders/passes/physics-debug.d.ts.map +0 -1
  73. package/dist/shaders/passes/physics-debug.js +0 -69
@@ -0,0 +1,136 @@
1
+ // M_Face as a StyleGraph — port of shaders/materials/face.ts (仿深空之眼 "M_Face").
2
+ // Toon + warm rim + dual fresnel rim + BT.601 bright-tex gate, mixed 50/50 against a
3
+ // Principled BSDF with noise bump. Structurally close to body, but: the toon uses the
4
+ // edge-AA ramp, hue tints are 0.46 (full hue_sat, not the 0.5 _id specialization),
5
+ // rim2 is the hair-style fresnel×layer_weight_fresnel rim, and there's an extra
6
+ // near-white texture gate that emits (freckle/highlight paint). Plain material — no
7
+ // built-in slot effect, so it uses the default prelude/epilogue.
8
+
9
+ import type { StyleGraph } from "../schema"
10
+
11
+ export const FACE_GRAPH: StyleGraph = {
12
+ version: 1,
13
+ name: "Face",
14
+ slot: "face",
15
+ nodes: [
16
+ { id: "tex", type: "texture" },
17
+ { id: "geo", type: "geometry" },
18
+
19
+ // ── toon shading ──
20
+ { id: "str", type: "shader_to_rgb_diffuse" },
21
+ { id: "toon", type: "ramp_constant_aa", inputs: { edge: 0.2966 } },
22
+ { id: "shadow_tint", type: "hue_sat", inputs: { hue: 0.46000000834465027, saturation: 2.0, value: 0.3499999940395355, fac: 1.0 } },
23
+ { id: "lit_tint", type: "hue_sat", inputs: { hue: 0.46000000834465027, saturation: 1.600000023841858, value: 1.5, fac: 1.0 } },
24
+ { id: "toon_color", type: "mix/blend" },
25
+ { id: "bc", type: "bright_contrast", inputs: { bright: 0.1, contrast: 0.2 } },
26
+ { id: "emission3", type: "emission", inputs: { strength: 2.5 } },
27
+
28
+ // ── warm rim (toon*0.5+0.5 → cardinal ramp) ──
29
+ { id: "warm_mul", type: "math/multiply", inputs: { b: 0.5 } },
30
+ { id: "warm_add", type: "math/add", inputs: { b: 0.5 } },
31
+ { id: "warm_clamp", type: "math/clamp01" },
32
+ {
33
+ id: "warm_ramp",
34
+ type: "ramp_cardinal",
35
+ inputs: {
36
+ pos0: 0.2409,
37
+ color0: [0.2426, 0.068, 0.0588, 1.0],
38
+ pos1: 0.4663,
39
+ color1: [0.6677, 0.5024, 0.5126, 1.0],
40
+ },
41
+ },
42
+ { id: "warm_emit", type: "emission", inputs: { strength: 0.30000001192092896 } },
43
+
44
+ // ── rim1: fresnel × facing ──
45
+ { id: "rim1_fres", type: "fresnel", inputs: { ior: 2.0 } },
46
+ { id: "rim1_lw", type: "layer_weight/facing", inputs: { blend: 0.24 } },
47
+ { id: "rim1_str", type: "math/multiply" },
48
+ { id: "rim1", type: "emission", inputs: { color: [0.984157919883728, 0.6110184788703918, 0.5736401677131653] } },
49
+
50
+ // ── rim2: fresnel × fresnel-layer-weight, powered (hair-style) ──
51
+ { id: "rim2_fres", type: "fresnel", inputs: { ior: 1.45 } },
52
+ { id: "rim2_lw", type: "layer_weight/fresnel", inputs: { blend: 0.61 } },
53
+ { id: "rim2_raw", type: "math/multiply" },
54
+ { id: "rim2_pow", type: "math/power", inputs: { b: 0.6300000548362732 } },
55
+ { id: "rim2_mix", type: "mix_shader", inputs: { b: [1.0, 0.4684903025627136, 0.3698573112487793] } },
56
+
57
+ // ── near-white texture gate emission ──
58
+ { id: "gate", type: "math/greater_than", inputs: { b: 0.9300000071525574 } },
59
+ { id: "gate_scale", type: "math/multiply", inputs: { b: 3.0 } },
60
+
61
+ // ── npr stack (rim1 + rim2 + bright_emit + warm) ──
62
+ { id: "npr_add1", type: "add_shader" },
63
+ { id: "npr_add2", type: "add_shader" },
64
+ { id: "npr_stack", type: "add_shader" },
65
+
66
+ // ── principled with noise bump ──
67
+ { id: "map", type: "mapping", inputs: { scl: [1.0, 1.0, 1.5] } },
68
+ { id: "noise", type: "tex_noise", inputs: { scale: 1.0 } },
69
+ { id: "noise_ramp", type: "ramp_linear", inputs: { pos0: 0.0, pos1: 1.0 } },
70
+ { id: "bump", type: "bump", inputs: { strength: 0.324644535779953 } },
71
+ { id: "principled_base", type: "mix/blend", inputs: { b: [0.6832, 0.1947, 0.1373] } },
72
+ { id: "p_emit", type: "emission", inputs: { strength: 0.2 } },
73
+ {
74
+ id: "principled",
75
+ type: "principled",
76
+ inputs: { metallic: 0.0, specular: 0.5, roughness: 0.3, spec_clamp: 10.0, sheen: 0.0, sheen_tint: 0.0 },
77
+ },
78
+ { id: "p_sum", type: "add_shader" },
79
+
80
+ { id: "mix_shader_001", type: "mix_shader", inputs: { fac: 0.5 } },
81
+ ],
82
+ links: [
83
+ // toon
84
+ { from: { node: "str", socket: "value" }, to: { node: "toon", socket: "fac" } },
85
+ { from: { node: "tex", socket: "color" }, to: { node: "shadow_tint", socket: "color" } },
86
+ { from: { node: "tex", socket: "color" }, to: { node: "lit_tint", socket: "color" } },
87
+ { from: { node: "toon", socket: "fac_out" }, to: { node: "toon_color", socket: "fac" } },
88
+ { from: { node: "shadow_tint", socket: "color" }, to: { node: "toon_color", socket: "a" } },
89
+ { from: { node: "lit_tint", socket: "color" }, to: { node: "toon_color", socket: "b" } },
90
+ { from: { node: "toon_color", socket: "color" }, to: { node: "bc", socket: "color" } },
91
+ { from: { node: "bc", socket: "color" }, to: { node: "emission3", socket: "color" } },
92
+ // warm rim
93
+ { from: { node: "toon", socket: "fac_out" }, to: { node: "warm_mul", socket: "a" } },
94
+ { from: { node: "warm_mul", socket: "value" }, to: { node: "warm_add", socket: "a" } },
95
+ { from: { node: "warm_add", socket: "value" }, to: { node: "warm_clamp", socket: "a" } },
96
+ { from: { node: "warm_clamp", socket: "value" }, to: { node: "warm_ramp", socket: "fac" } },
97
+ { from: { node: "warm_ramp", socket: "color" }, to: { node: "warm_emit", socket: "color" } },
98
+ // rim1
99
+ { from: { node: "rim1_fres", socket: "value" }, to: { node: "rim1_str", socket: "a" } },
100
+ { from: { node: "rim1_lw", socket: "value" }, to: { node: "rim1_str", socket: "b" } },
101
+ { from: { node: "rim1_str", socket: "value" }, to: { node: "rim1", socket: "strength" } },
102
+ // rim2
103
+ { from: { node: "rim2_fres", socket: "value" }, to: { node: "rim2_raw", socket: "a" } },
104
+ { from: { node: "rim2_lw", socket: "value" }, to: { node: "rim2_raw", socket: "b" } },
105
+ { from: { node: "rim2_raw", socket: "value" }, to: { node: "rim2_pow", socket: "a" } },
106
+ { from: { node: "emission3", socket: "color" }, to: { node: "rim2_mix", socket: "a" } },
107
+ { from: { node: "rim2_pow", socket: "value" }, to: { node: "rim2_mix", socket: "fac" } },
108
+ // gate
109
+ { from: { node: "tex", socket: "color" }, to: { node: "gate", socket: "a" } },
110
+ { from: { node: "gate", socket: "value" }, to: { node: "gate_scale", socket: "a" } },
111
+ // npr stack
112
+ { from: { node: "rim1", socket: "color" }, to: { node: "npr_add1", socket: "a" } },
113
+ { from: { node: "rim2_mix", socket: "color" }, to: { node: "npr_add1", socket: "b" } },
114
+ { from: { node: "npr_add1", socket: "color" }, to: { node: "npr_add2", socket: "a" } },
115
+ { from: { node: "gate_scale", socket: "value" }, to: { node: "npr_add2", socket: "b" } },
116
+ { from: { node: "npr_add2", socket: "color" }, to: { node: "npr_stack", socket: "a" } },
117
+ { from: { node: "warm_emit", socket: "color" }, to: { node: "npr_stack", socket: "b" } },
118
+ // principled + noise bump
119
+ { from: { node: "geo", socket: "rest_pos" }, to: { node: "map", socket: "vector" } },
120
+ { from: { node: "map", socket: "vector" }, to: { node: "noise", socket: "vector" } },
121
+ { from: { node: "noise", socket: "value" }, to: { node: "noise_ramp", socket: "fac" } },
122
+ { from: { node: "noise_ramp", socket: "fac_out" }, to: { node: "bump", socket: "height" } },
123
+ { from: { node: "geo", socket: "normal" }, to: { node: "bump", socket: "normal" } },
124
+ { from: { node: "noise_ramp", socket: "fac_out" }, to: { node: "principled_base", socket: "fac" } },
125
+ { from: { node: "bc", socket: "color" }, to: { node: "principled_base", socket: "a" } },
126
+ { from: { node: "bc", socket: "color" }, to: { node: "p_emit", socket: "color" } },
127
+ { from: { node: "principled_base", socket: "color" }, to: { node: "principled", socket: "base" } },
128
+ { from: { node: "bump", socket: "vector" }, to: { node: "principled", socket: "normal" } },
129
+ { from: { node: "principled", socket: "color" }, to: { node: "p_sum", socket: "a" } },
130
+ { from: { node: "p_emit", socket: "color" }, to: { node: "p_sum", socket: "b" } },
131
+ // final mix
132
+ { from: { node: "npr_stack", socket: "color" }, to: { node: "mix_shader_001", socket: "a" } },
133
+ { from: { node: "p_sum", socket: "color" }, to: { node: "mix_shader_001", socket: "b" } },
134
+ ],
135
+ output: { node: "mix_shader_001", socket: "color" },
136
+ }
@@ -0,0 +1,82 @@
1
+ // M_Hair — 仿深空之眼渲染预设v1.0_by_小绿毛猫, as a StyleGraph. Node ids mirror the
2
+ // Blender node names referenced in shaders/materials/hair.ts comments; compiled with
3
+ // { inlineParams: true } this graph must reproduce HAIR_SHADER_WGSL's fragment body
4
+ // (golden test #1 — see tests/graph.test.mjs).
5
+ //
6
+ // Inherited authoring decisions from the hand port: the noise→bump subtree on
7
+ // Principled.Normal is omitted (imperceptible at 0.2 mix weight), and Blender's bevel
8
+ // node is approximated by saturate(normal.y) — Blender Z-up ⇒ engine Y-up.
9
+ //
10
+ // The object is pure JSON (no functions/undefined) — JSON.stringify round-trips it,
11
+ // which is how reze.design will ship additional presets.
12
+
13
+ import type { StyleGraph } from "../schema"
14
+
15
+ export const HAIR_GRAPH: StyleGraph = {
16
+ version: 1,
17
+ name: "Hair",
18
+ slot: "hair",
19
+ nodes: [
20
+ { id: "tex", type: "texture" },
21
+ { id: "geo", type: "geometry" },
22
+ { id: "hs_shadow", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.2, value: 0.5, fac: 1.0 } },
23
+ { id: "hs_002", type: "hue_sat", inputs: { hue: 0.48, saturation: 1.2, value: 0.7, fac: 1.0 } },
24
+ { id: "hs_001", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.5, value: 1.0, fac: 1.0 } },
25
+ { id: "str", type: "shader_to_rgb_diffuse" },
26
+ { id: "ramp_008", type: "ramp_constant", inputs: { pos0: 0.0, color0: [0, 0, 0, 1], pos1: 0.2966, color1: [1, 1, 1, 1] } },
27
+ { id: "mix_004", type: "mix/blend" },
28
+ { id: "bc", type: "bright_contrast", inputs: { bright: 0.1, contrast: 0.2 } },
29
+ { id: "sep_n", type: "separate_xyz" },
30
+ { id: "bevel_clamp", type: "math/clamp01" },
31
+ { id: "mix_003", type: "mix/blend" },
32
+ { id: "fres", type: "fresnel", inputs: { ior: 1.45 } },
33
+ { id: "lw", type: "layer_weight/fresnel", inputs: { blend: 0.61 } },
34
+ { id: "rim_mul", type: "math/multiply" },
35
+ { id: "rim_pow", type: "math/power", inputs: { b: 0.6300000548362732 } },
36
+ {
37
+ id: "mix_shader_002",
38
+ type: "mix_shader",
39
+ inputs: { b: [0.1673291176557541, 0.1673291176557541, 0.1673291176557541] },
40
+ },
41
+ { id: "gate", type: "math/greater_than", inputs: { b: 0.15000000596046448 } },
42
+ { id: "gate_scale", type: "math/multiply", inputs: { b: 0.1 } },
43
+ { id: "npr_add", type: "mix/add_emit" },
44
+ {
45
+ id: "principled",
46
+ type: "principled",
47
+ inputs: { metallic: 0.0, specular: 1.0, roughness: 0.3, spec_clamp: 10.0, sheen: 0.0, sheen_tint: 0.0 },
48
+ },
49
+ { id: "mix_shader_001", type: "mix_shader", inputs: { fac: 0.2 } },
50
+ ],
51
+ links: [
52
+ { from: { node: "tex", socket: "color" }, to: { node: "hs_shadow", socket: "color" } },
53
+ { from: { node: "hs_shadow", socket: "color" }, to: { node: "hs_002", socket: "color" } },
54
+ { from: { node: "tex", socket: "color" }, to: { node: "hs_001", socket: "color" } },
55
+ { from: { node: "str", socket: "value" }, to: { node: "ramp_008", socket: "fac" } },
56
+ { from: { node: "ramp_008", socket: "fac_out" }, to: { node: "mix_004", socket: "fac" } },
57
+ { from: { node: "hs_002", socket: "color" }, to: { node: "mix_004", socket: "a" } },
58
+ { from: { node: "hs_001", socket: "color" }, to: { node: "mix_004", socket: "b" } },
59
+ { from: { node: "mix_004", socket: "color" }, to: { node: "bc", socket: "color" } },
60
+ { from: { node: "geo", socket: "normal" }, to: { node: "sep_n", socket: "vector" } },
61
+ { from: { node: "sep_n", socket: "y" }, to: { node: "bevel_clamp", socket: "a" } },
62
+ { from: { node: "bevel_clamp", socket: "value" }, to: { node: "mix_003", socket: "fac" } },
63
+ { from: { node: "bc", socket: "color" }, to: { node: "mix_003", socket: "a" } },
64
+ { from: { node: "hs_002", socket: "color" }, to: { node: "mix_003", socket: "b" } },
65
+ { from: { node: "fres", socket: "value" }, to: { node: "rim_mul", socket: "a" } },
66
+ { from: { node: "lw", socket: "value" }, to: { node: "rim_mul", socket: "b" } },
67
+ { from: { node: "rim_mul", socket: "value" }, to: { node: "rim_pow", socket: "a" } },
68
+ { from: { node: "mix_003", socket: "color" }, to: { node: "mix_shader_002", socket: "a" } },
69
+ { from: { node: "rim_pow", socket: "value" }, to: { node: "mix_shader_002", socket: "fac" } },
70
+ { from: { node: "tex", socket: "color" }, to: { node: "gate", socket: "a" } },
71
+ { from: { node: "gate", socket: "value" }, to: { node: "gate_scale", socket: "a" } },
72
+ { from: { node: "mix_shader_002", socket: "color" }, to: { node: "npr_add", socket: "a" } },
73
+ { from: { node: "gate_scale", socket: "value" }, to: { node: "npr_add", socket: "b" } },
74
+ { from: { node: "bc", socket: "color" }, to: { node: "principled", socket: "base" } },
75
+ { from: { node: "npr_add", socket: "color" }, to: { node: "mix_shader_001", socket: "a" } },
76
+ { from: { node: "principled", socket: "color" }, to: { node: "mix_shader_001", socket: "b" } },
77
+ ],
78
+ output: { node: "mix_shader_001", socket: "color" },
79
+ // Adjust-tier params deliberately absent: which sockets deserve sliders (and what
80
+ // they're called) is preset-author curation done in reze.design, not engine data.
81
+ // The exposed-param mechanism itself is covered by tests/graph.test.mjs.
82
+ }
@@ -0,0 +1,61 @@
1
+ // M_Metal as a StyleGraph — port of shaders/materials/metal.ts.
2
+ // Metallic Principled (Metallic=1, Specular=1, Roughness=0.3) with a
3
+ // reflection-coord voronoi driving base color (metallic sparkle), plus an NPR
4
+ // toon/overlay emission stack mixed at Fac=0.6967. The voronoi Color→ramp Fac
5
+ // link goes through Blender's implicit BT.601 conversion (color_to_value).
6
+
7
+ import type { StyleGraph } from "../schema"
8
+
9
+ export const METAL_GRAPH: StyleGraph = {
10
+ version: 1,
11
+ name: "Metal",
12
+ slot: "metal",
13
+ nodes: [
14
+ { id: "tex", type: "texture" },
15
+ { id: "geo", type: "geometry" },
16
+ { id: "tex_tint", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.0, value: 0.800000011920929, fac: 1.0 } },
17
+ { id: "str", type: "shader_to_rgb_diffuse" },
18
+ { id: "ramp_008", type: "ramp_constant_aa", inputs: { edge: 0.2966 } },
19
+ { id: "mix04_fac", type: "math/multiply", inputs: { b: 0.5 } },
20
+ { id: "dark_tex", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.0, value: 0.19999998807907104, fac: 1.0 } },
21
+ { id: "mix_004", type: "mix/blend" },
22
+ { id: "hue_004", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.0, value: 2.0, fac: 1.0 } },
23
+ { id: "npr_overlay", type: "mix/overlay", inputs: { fac: 1.0 } },
24
+ { id: "npr_emit", type: "emission", inputs: { strength: 8.100000381469727 } },
25
+ { id: "voro_cross", type: "vect_cross", inputs: { b: [0, 1, 0] } },
26
+ { id: "voro", type: "tex_voronoi/color", inputs: { scale: 4.3 } },
27
+ { id: "voro_ramp", type: "ramp_linear", inputs: { pos0: 0.0, pos1: 1.0 } },
28
+ { id: "hue_006", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.5, value: 1.2999999523162842, fac: 1.0 } },
29
+ { id: "albedo", type: "mix/blend" },
30
+ {
31
+ id: "principled",
32
+ type: "principled",
33
+ inputs: { metallic: 1.0, specular: 1.0, roughness: 0.3, spec_clamp: 1e30, sheen: 0.0, sheen_tint: 0.0 },
34
+ },
35
+ { id: "mix_shader_001", type: "mix_shader", inputs: { fac: 0.6967 } },
36
+ ],
37
+ links: [
38
+ { from: { node: "tex", socket: "color" }, to: { node: "tex_tint", socket: "color" } },
39
+ { from: { node: "str", socket: "value" }, to: { node: "ramp_008", socket: "fac" } },
40
+ { from: { node: "ramp_008", socket: "fac_out" }, to: { node: "mix04_fac", socket: "a" } },
41
+ { from: { node: "tex_tint", socket: "color" }, to: { node: "dark_tex", socket: "color" } },
42
+ { from: { node: "mix04_fac", socket: "value" }, to: { node: "mix_004", socket: "fac" } },
43
+ { from: { node: "dark_tex", socket: "color" }, to: { node: "mix_004", socket: "a" } },
44
+ { from: { node: "tex_tint", socket: "color" }, to: { node: "mix_004", socket: "b" } },
45
+ { from: { node: "mix_004", socket: "color" }, to: { node: "hue_004", socket: "color" } },
46
+ { from: { node: "mix_004", socket: "color" }, to: { node: "npr_overlay", socket: "a" } },
47
+ { from: { node: "hue_004", socket: "color" }, to: { node: "npr_overlay", socket: "b" } },
48
+ { from: { node: "npr_overlay", socket: "color" }, to: { node: "npr_emit", socket: "color" } },
49
+ { from: { node: "geo", socket: "reflection" }, to: { node: "voro_cross", socket: "a" } },
50
+ { from: { node: "voro_cross", socket: "vector" }, to: { node: "voro", socket: "vector" } },
51
+ { from: { node: "voro", socket: "color" }, to: { node: "voro_ramp", socket: "fac" } },
52
+ { from: { node: "tex_tint", socket: "color" }, to: { node: "hue_006", socket: "color" } },
53
+ { from: { node: "voro_ramp", socket: "fac_out" }, to: { node: "albedo", socket: "fac" } },
54
+ { from: { node: "voro_ramp", socket: "fac_out" }, to: { node: "albedo", socket: "a" } },
55
+ { from: { node: "hue_006", socket: "color" }, to: { node: "albedo", socket: "b" } },
56
+ { from: { node: "albedo", socket: "color" }, to: { node: "principled", socket: "base" } },
57
+ { from: { node: "npr_emit", socket: "color" }, to: { node: "mix_shader_001", socket: "a" } },
58
+ { from: { node: "principled", socket: "color" }, to: { node: "mix_shader_001", socket: "b" } },
59
+ ],
60
+ output: { node: "mix_shader_001", socket: "color" },
61
+ }
@@ -0,0 +1,57 @@
1
+ // M_Stockings as a StyleGraph — port of shaders/materials/stockings.ts.
2
+ // A bbox-gradient × facing-rim mask drives a Mix Shader between an HSV-boosted
3
+ // emission (val 5×) and a sheen Principled. The hashed-alpha discard and the
4
+ // alpha=1 output are slot-owned (see STOCKINGS_TEMPLATE in slots.ts) — the graph
5
+ // computes only the radiance. Blender's Generated coord is approximated with UV,
6
+ // as in the hand port. The grayscale mask feeds Mix Shader Fac through Blender's
7
+ // implicit BT.601 color→float conversion (equal-component vector → same scalar).
8
+
9
+ import type { StyleGraph } from "../schema"
10
+
11
+ export const STOCKINGS_GRAPH: StyleGraph = {
12
+ version: 1,
13
+ name: "Stockings",
14
+ slot: "stockings",
15
+ nodes: [
16
+ { id: "tex", type: "texture" },
17
+ { id: "geo", type: "geometry" },
18
+ { id: "map", type: "mapping", inputs: { loc: [1.0, 1.0, 1.0], rot: [0.0, 1.5708, 1.5708] } },
19
+ { id: "grad", type: "tex_gradient" },
20
+ { id: "ramp_001", type: "ramp_tri" },
21
+ { id: "ramp_002", type: "ramp_cardinal", inputs: { pos0: 0.0, pos1: 0.9565 } },
22
+ { id: "facing", type: "layer_weight/facing", inputs: { blend: 0.4 } },
23
+ { id: "ramp_face", type: "ramp_cardinal", inputs: { pos0: 0.0, pos1: 0.5435 } },
24
+ { id: "mix_001", type: "mix/blend", inputs: { fac: 0.5, a: [1.0, 1.0, 1.0] } },
25
+ { id: "mask", type: "mix/lighten", inputs: { fac: 0.5 } },
26
+ { id: "emission_hs", type: "hue_sat", inputs: { hue: 0.5, saturation: 1.0, value: 5.0, fac: 1.0 } },
27
+ {
28
+ id: "principled",
29
+ type: "principled",
30
+ inputs: {
31
+ metallic: 0.1,
32
+ specular: 1.0,
33
+ roughness: 0.5,
34
+ spec_clamp: 1e30,
35
+ sheen: 0.7017999887466431,
36
+ sheen_tint: 0.5,
37
+ },
38
+ },
39
+ { id: "mix_shader_001", type: "mix_shader" },
40
+ ],
41
+ links: [
42
+ { from: { node: "geo", socket: "uv" }, to: { node: "map", socket: "vector" } },
43
+ { from: { node: "map", socket: "vector" }, to: { node: "grad", socket: "vector" } },
44
+ { from: { node: "grad", socket: "value" }, to: { node: "ramp_001", socket: "fac" } },
45
+ { from: { node: "ramp_001", socket: "value" }, to: { node: "ramp_002", socket: "fac" } },
46
+ { from: { node: "facing", socket: "value" }, to: { node: "ramp_face", socket: "fac" } },
47
+ { from: { node: "ramp_face", socket: "fac_out" }, to: { node: "mix_001", socket: "b" } },
48
+ { from: { node: "mix_001", socket: "color" }, to: { node: "mask", socket: "a" } },
49
+ { from: { node: "ramp_002", socket: "fac_out" }, to: { node: "mask", socket: "b" } },
50
+ { from: { node: "tex", socket: "color" }, to: { node: "emission_hs", socket: "color" } },
51
+ { from: { node: "tex", socket: "color" }, to: { node: "principled", socket: "base" } },
52
+ { from: { node: "emission_hs", socket: "color" }, to: { node: "mix_shader_001", socket: "a" } },
53
+ { from: { node: "principled", socket: "color" }, to: { node: "mix_shader_001", socket: "b" } },
54
+ { from: { node: "mask", socket: "color" }, to: { node: "mix_shader_001", socket: "fac" } },
55
+ ],
56
+ output: { node: "mix_shader_001", socket: "color" },
57
+ }