@triforge/shader-core 0.1.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.
Files changed (297) hide show
  1. package/README.md +90 -0
  2. package/dist/bundle.js +5578 -0
  3. package/dist/core/CompileContext.d.ts +60 -0
  4. package/dist/core/CompileContext.d.ts.map +1 -0
  5. package/dist/core/CompileContext.js +276 -0
  6. package/dist/core/InputNode.d.ts +11 -0
  7. package/dist/core/InputNode.d.ts.map +1 -0
  8. package/dist/core/InputNode.js +13 -0
  9. package/dist/core/InputSocket.d.ts +21 -0
  10. package/dist/core/InputSocket.d.ts.map +1 -0
  11. package/dist/core/InputSocket.js +23 -0
  12. package/dist/core/OutputNode.d.ts +30 -0
  13. package/dist/core/OutputNode.d.ts.map +1 -0
  14. package/dist/core/OutputNode.js +60 -0
  15. package/dist/core/OutputSocket.d.ts +18 -0
  16. package/dist/core/OutputSocket.d.ts.map +1 -0
  17. package/dist/core/OutputSocket.js +16 -0
  18. package/dist/core/ProcessNode.d.ts +8 -0
  19. package/dist/core/ProcessNode.d.ts.map +1 -0
  20. package/dist/core/ProcessNode.js +7 -0
  21. package/dist/core/ShaderConfig.d.ts +13 -0
  22. package/dist/core/ShaderConfig.d.ts.map +1 -0
  23. package/dist/core/ShaderConfig.js +11 -0
  24. package/dist/core/ShaderNode.d.ts +114 -0
  25. package/dist/core/ShaderNode.d.ts.map +1 -0
  26. package/dist/core/ShaderNode.js +156 -0
  27. package/dist/core/ShaderNodeError.d.ts +32 -0
  28. package/dist/core/ShaderNodeError.d.ts.map +1 -0
  29. package/dist/core/ShaderNodeError.js +61 -0
  30. package/dist/core/SocketType.d.ts +12 -0
  31. package/dist/core/SocketType.d.ts.map +1 -0
  32. package/dist/core/SocketType.js +7 -0
  33. package/dist/index.d.ts +164 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +108 -0
  36. package/dist/nodes/input/Attribute.d.ts +45 -0
  37. package/dist/nodes/input/Attribute.d.ts.map +1 -0
  38. package/dist/nodes/input/Attribute.js +58 -0
  39. package/dist/nodes/input/CameraData.d.ts +21 -0
  40. package/dist/nodes/input/CameraData.d.ts.map +1 -0
  41. package/dist/nodes/input/CameraData.js +33 -0
  42. package/dist/nodes/input/ColorAttribute.d.ts +28 -0
  43. package/dist/nodes/input/ColorAttribute.d.ts.map +1 -0
  44. package/dist/nodes/input/ColorAttribute.js +32 -0
  45. package/dist/nodes/input/Geometry.d.ts +23 -0
  46. package/dist/nodes/input/Geometry.d.ts.map +1 -0
  47. package/dist/nodes/input/Geometry.js +38 -0
  48. package/dist/nodes/input/HairInfo.d.ts +38 -0
  49. package/dist/nodes/input/HairInfo.d.ts.map +1 -0
  50. package/dist/nodes/input/HairInfo.js +50 -0
  51. package/dist/nodes/input/LayerWeight.d.ts +26 -0
  52. package/dist/nodes/input/LayerWeight.d.ts.map +1 -0
  53. package/dist/nodes/input/LayerWeight.js +35 -0
  54. package/dist/nodes/input/LightPath.d.ts +60 -0
  55. package/dist/nodes/input/LightPath.d.ts.map +1 -0
  56. package/dist/nodes/input/LightPath.js +112 -0
  57. package/dist/nodes/input/ObjectInfo.d.ts +22 -0
  58. package/dist/nodes/input/ObjectInfo.d.ts.map +1 -0
  59. package/dist/nodes/input/ObjectInfo.js +41 -0
  60. package/dist/nodes/input/OceanAttribute.d.ts +32 -0
  61. package/dist/nodes/input/OceanAttribute.d.ts.map +1 -0
  62. package/dist/nodes/input/OceanAttribute.js +38 -0
  63. package/dist/nodes/input/ParticleInfo.d.ts +31 -0
  64. package/dist/nodes/input/ParticleInfo.d.ts.map +1 -0
  65. package/dist/nodes/input/ParticleInfo.js +44 -0
  66. package/dist/nodes/input/RGB.d.ts +19 -0
  67. package/dist/nodes/input/RGB.d.ts.map +1 -0
  68. package/dist/nodes/input/RGB.js +23 -0
  69. package/dist/nodes/input/ScreenCamera.d.ts +37 -0
  70. package/dist/nodes/input/ScreenCamera.d.ts.map +1 -0
  71. package/dist/nodes/input/ScreenCamera.js +59 -0
  72. package/dist/nodes/input/Tangent.d.ts +21 -0
  73. package/dist/nodes/input/Tangent.d.ts.map +1 -0
  74. package/dist/nodes/input/Tangent.js +30 -0
  75. package/dist/nodes/input/TextureCoordinate.d.ts +17 -0
  76. package/dist/nodes/input/TextureCoordinate.d.ts.map +1 -0
  77. package/dist/nodes/input/TextureCoordinate.js +24 -0
  78. package/dist/nodes/input/UVMap.d.ts +20 -0
  79. package/dist/nodes/input/UVMap.d.ts.map +1 -0
  80. package/dist/nodes/input/UVMap.js +23 -0
  81. package/dist/nodes/input/Value.d.ts +19 -0
  82. package/dist/nodes/input/Value.d.ts.map +1 -0
  83. package/dist/nodes/input/Value.js +22 -0
  84. package/dist/nodes/input/Wireframe.d.ts +25 -0
  85. package/dist/nodes/input/Wireframe.d.ts.map +1 -0
  86. package/dist/nodes/input/Wireframe.js +30 -0
  87. package/dist/nodes/output/Displacement.d.ts +28 -0
  88. package/dist/nodes/output/Displacement.d.ts.map +1 -0
  89. package/dist/nodes/output/Displacement.js +34 -0
  90. package/dist/nodes/output/MaterialOutput.d.ts +43 -0
  91. package/dist/nodes/output/MaterialOutput.d.ts.map +1 -0
  92. package/dist/nodes/output/MaterialOutput.js +118 -0
  93. package/dist/nodes/output/ScreenOutput.d.ts +38 -0
  94. package/dist/nodes/output/ScreenOutput.d.ts.map +1 -0
  95. package/dist/nodes/output/ScreenOutput.js +88 -0
  96. package/dist/nodes/process/AddShader.d.ts +30 -0
  97. package/dist/nodes/process/AddShader.d.ts.map +1 -0
  98. package/dist/nodes/process/AddShader.js +36 -0
  99. package/dist/nodes/process/AnimatedNoiseTexture.d.ts +39 -0
  100. package/dist/nodes/process/AnimatedNoiseTexture.d.ts.map +1 -0
  101. package/dist/nodes/process/AnimatedNoiseTexture.js +93 -0
  102. package/dist/nodes/process/Blackbody.d.ts +29 -0
  103. package/dist/nodes/process/Blackbody.d.ts.map +1 -0
  104. package/dist/nodes/process/Blackbody.js +50 -0
  105. package/dist/nodes/process/BrickTexture.d.ts +36 -0
  106. package/dist/nodes/process/BrickTexture.d.ts.map +1 -0
  107. package/dist/nodes/process/BrickTexture.js +71 -0
  108. package/dist/nodes/process/BrightContrast.d.ts +30 -0
  109. package/dist/nodes/process/BrightContrast.d.ts.map +1 -0
  110. package/dist/nodes/process/BrightContrast.js +41 -0
  111. package/dist/nodes/process/Bump.d.ts +31 -0
  112. package/dist/nodes/process/Bump.d.ts.map +1 -0
  113. package/dist/nodes/process/Bump.js +65 -0
  114. package/dist/nodes/process/CheckerTexture.d.ts +30 -0
  115. package/dist/nodes/process/CheckerTexture.d.ts.map +1 -0
  116. package/dist/nodes/process/CheckerTexture.js +48 -0
  117. package/dist/nodes/process/Clamp.d.ts +32 -0
  118. package/dist/nodes/process/Clamp.d.ts.map +1 -0
  119. package/dist/nodes/process/Clamp.js +37 -0
  120. package/dist/nodes/process/ColorRamp.d.ts +28 -0
  121. package/dist/nodes/process/ColorRamp.d.ts.map +1 -0
  122. package/dist/nodes/process/ColorRamp.js +49 -0
  123. package/dist/nodes/process/CombineColor.d.ts +34 -0
  124. package/dist/nodes/process/CombineColor.d.ts.map +1 -0
  125. package/dist/nodes/process/CombineColor.js +69 -0
  126. package/dist/nodes/process/CombineRGB.d.ts +29 -0
  127. package/dist/nodes/process/CombineRGB.d.ts.map +1 -0
  128. package/dist/nodes/process/CombineRGB.js +33 -0
  129. package/dist/nodes/process/CombineXYZ.d.ts +29 -0
  130. package/dist/nodes/process/CombineXYZ.d.ts.map +1 -0
  131. package/dist/nodes/process/CombineXYZ.js +33 -0
  132. package/dist/nodes/process/DiffuseBSDF.d.ts +30 -0
  133. package/dist/nodes/process/DiffuseBSDF.d.ts.map +1 -0
  134. package/dist/nodes/process/DiffuseBSDF.js +43 -0
  135. package/dist/nodes/process/Emission.d.ts +30 -0
  136. package/dist/nodes/process/Emission.d.ts.map +1 -0
  137. package/dist/nodes/process/Emission.js +36 -0
  138. package/dist/nodes/process/EnvironmentTexture.d.ts +41 -0
  139. package/dist/nodes/process/EnvironmentTexture.d.ts.map +1 -0
  140. package/dist/nodes/process/EnvironmentTexture.js +65 -0
  141. package/dist/nodes/process/FloatCurve.d.ts +34 -0
  142. package/dist/nodes/process/FloatCurve.d.ts.map +1 -0
  143. package/dist/nodes/process/FloatCurve.js +46 -0
  144. package/dist/nodes/process/Fresnel.d.ts +36 -0
  145. package/dist/nodes/process/Fresnel.d.ts.map +1 -0
  146. package/dist/nodes/process/Fresnel.js +53 -0
  147. package/dist/nodes/process/Gamma.d.ts +29 -0
  148. package/dist/nodes/process/Gamma.d.ts.map +1 -0
  149. package/dist/nodes/process/Gamma.js +35 -0
  150. package/dist/nodes/process/GlassBSDF.d.ts +31 -0
  151. package/dist/nodes/process/GlassBSDF.d.ts.map +1 -0
  152. package/dist/nodes/process/GlassBSDF.js +51 -0
  153. package/dist/nodes/process/GlossyBSDF.d.ts +30 -0
  154. package/dist/nodes/process/GlossyBSDF.d.ts.map +1 -0
  155. package/dist/nodes/process/GlossyBSDF.js +50 -0
  156. package/dist/nodes/process/GradientTexture.d.ts +31 -0
  157. package/dist/nodes/process/GradientTexture.d.ts.map +1 -0
  158. package/dist/nodes/process/GradientTexture.js +49 -0
  159. package/dist/nodes/process/HashValue.d.ts +30 -0
  160. package/dist/nodes/process/HashValue.d.ts.map +1 -0
  161. package/dist/nodes/process/HashValue.js +34 -0
  162. package/dist/nodes/process/HueSaturationValue.d.ts +32 -0
  163. package/dist/nodes/process/HueSaturationValue.d.ts.map +1 -0
  164. package/dist/nodes/process/HueSaturationValue.js +58 -0
  165. package/dist/nodes/process/ImageTexture.d.ts +34 -0
  166. package/dist/nodes/process/ImageTexture.d.ts.map +1 -0
  167. package/dist/nodes/process/ImageTexture.js +53 -0
  168. package/dist/nodes/process/InvertColor.d.ts +29 -0
  169. package/dist/nodes/process/InvertColor.d.ts.map +1 -0
  170. package/dist/nodes/process/InvertColor.js +35 -0
  171. package/dist/nodes/process/MagicTexture.d.ts +30 -0
  172. package/dist/nodes/process/MagicTexture.d.ts.map +1 -0
  173. package/dist/nodes/process/MagicTexture.js +54 -0
  174. package/dist/nodes/process/MapRange.d.ts +38 -0
  175. package/dist/nodes/process/MapRange.d.ts.map +1 -0
  176. package/dist/nodes/process/MapRange.js +52 -0
  177. package/dist/nodes/process/Mapping.d.ts +37 -0
  178. package/dist/nodes/process/Mapping.d.ts.map +1 -0
  179. package/dist/nodes/process/Mapping.js +57 -0
  180. package/dist/nodes/process/Math.d.ts +40 -0
  181. package/dist/nodes/process/Math.d.ts.map +1 -0
  182. package/dist/nodes/process/Math.js +100 -0
  183. package/dist/nodes/process/MixRGB.d.ts +35 -0
  184. package/dist/nodes/process/MixRGB.d.ts.map +1 -0
  185. package/dist/nodes/process/MixRGB.js +63 -0
  186. package/dist/nodes/process/MixShader.d.ts +35 -0
  187. package/dist/nodes/process/MixShader.d.ts.map +1 -0
  188. package/dist/nodes/process/MixShader.js +47 -0
  189. package/dist/nodes/process/MusgraveTexture.d.ts +36 -0
  190. package/dist/nodes/process/MusgraveTexture.d.ts.map +1 -0
  191. package/dist/nodes/process/MusgraveTexture.js +70 -0
  192. package/dist/nodes/process/NoiseTexture.d.ts +31 -0
  193. package/dist/nodes/process/NoiseTexture.d.ts.map +1 -0
  194. package/dist/nodes/process/NoiseTexture.js +78 -0
  195. package/dist/nodes/process/Normal.d.ts +30 -0
  196. package/dist/nodes/process/Normal.d.ts.map +1 -0
  197. package/dist/nodes/process/Normal.js +38 -0
  198. package/dist/nodes/process/NormalMap.d.ts +34 -0
  199. package/dist/nodes/process/NormalMap.d.ts.map +1 -0
  200. package/dist/nodes/process/NormalMap.js +54 -0
  201. package/dist/nodes/process/PrincipledBSDF.d.ts +32 -0
  202. package/dist/nodes/process/PrincipledBSDF.d.ts.map +1 -0
  203. package/dist/nodes/process/PrincipledBSDF.js +75 -0
  204. package/dist/nodes/process/PrincipledHair.d.ts +63 -0
  205. package/dist/nodes/process/PrincipledHair.d.ts.map +1 -0
  206. package/dist/nodes/process/PrincipledHair.js +137 -0
  207. package/dist/nodes/process/PrincipledVolume.d.ts +37 -0
  208. package/dist/nodes/process/PrincipledVolume.d.ts.map +1 -0
  209. package/dist/nodes/process/PrincipledVolume.js +67 -0
  210. package/dist/nodes/process/RGBCurves.d.ts +45 -0
  211. package/dist/nodes/process/RGBCurves.d.ts.map +1 -0
  212. package/dist/nodes/process/RGBCurves.js +81 -0
  213. package/dist/nodes/process/RGBtoBW.d.ts +28 -0
  214. package/dist/nodes/process/RGBtoBW.d.ts.map +1 -0
  215. package/dist/nodes/process/RGBtoBW.js +31 -0
  216. package/dist/nodes/process/RefractionBSDF.d.ts +32 -0
  217. package/dist/nodes/process/RefractionBSDF.d.ts.map +1 -0
  218. package/dist/nodes/process/RefractionBSDF.js +46 -0
  219. package/dist/nodes/process/SchwarzschildMarch.d.ts +56 -0
  220. package/dist/nodes/process/SchwarzschildMarch.d.ts.map +1 -0
  221. package/dist/nodes/process/SchwarzschildMarch.js +306 -0
  222. package/dist/nodes/process/SeparateColor.d.ts +33 -0
  223. package/dist/nodes/process/SeparateColor.d.ts.map +1 -0
  224. package/dist/nodes/process/SeparateColor.js +79 -0
  225. package/dist/nodes/process/SeparateRGB.d.ts +27 -0
  226. package/dist/nodes/process/SeparateRGB.d.ts.map +1 -0
  227. package/dist/nodes/process/SeparateRGB.js +31 -0
  228. package/dist/nodes/process/SeparateXYZ.d.ts +27 -0
  229. package/dist/nodes/process/SeparateXYZ.d.ts.map +1 -0
  230. package/dist/nodes/process/SeparateXYZ.js +31 -0
  231. package/dist/nodes/process/ShaderScript.d.ts +95 -0
  232. package/dist/nodes/process/ShaderScript.d.ts.map +1 -0
  233. package/dist/nodes/process/ShaderScript.js +119 -0
  234. package/dist/nodes/process/ShaderToRGB.d.ts +28 -0
  235. package/dist/nodes/process/ShaderToRGB.d.ts.map +1 -0
  236. package/dist/nodes/process/ShaderToRGB.js +33 -0
  237. package/dist/nodes/process/SheenBSDF.d.ts +31 -0
  238. package/dist/nodes/process/SheenBSDF.d.ts.map +1 -0
  239. package/dist/nodes/process/SheenBSDF.js +49 -0
  240. package/dist/nodes/process/SpecularBSDF.d.ts +32 -0
  241. package/dist/nodes/process/SpecularBSDF.d.ts.map +1 -0
  242. package/dist/nodes/process/SpecularBSDF.js +54 -0
  243. package/dist/nodes/process/SubsurfaceScattering.d.ts +33 -0
  244. package/dist/nodes/process/SubsurfaceScattering.d.ts.map +1 -0
  245. package/dist/nodes/process/SubsurfaceScattering.js +46 -0
  246. package/dist/nodes/process/ToonBSDF.d.ts +31 -0
  247. package/dist/nodes/process/ToonBSDF.d.ts.map +1 -0
  248. package/dist/nodes/process/ToonBSDF.js +44 -0
  249. package/dist/nodes/process/TranslucentBSDF.d.ts +29 -0
  250. package/dist/nodes/process/TranslucentBSDF.d.ts.map +1 -0
  251. package/dist/nodes/process/TranslucentBSDF.js +39 -0
  252. package/dist/nodes/process/VectorCurves.d.ts +42 -0
  253. package/dist/nodes/process/VectorCurves.d.ts.map +1 -0
  254. package/dist/nodes/process/VectorCurves.js +71 -0
  255. package/dist/nodes/process/VectorMath.d.ts +38 -0
  256. package/dist/nodes/process/VectorMath.d.ts.map +1 -0
  257. package/dist/nodes/process/VectorMath.js +105 -0
  258. package/dist/nodes/process/VectorRotate.d.ts +34 -0
  259. package/dist/nodes/process/VectorRotate.d.ts.map +1 -0
  260. package/dist/nodes/process/VectorRotate.js +52 -0
  261. package/dist/nodes/process/VectorTransform.d.ts +36 -0
  262. package/dist/nodes/process/VectorTransform.d.ts.map +1 -0
  263. package/dist/nodes/process/VectorTransform.js +48 -0
  264. package/dist/nodes/process/VolumeAbsorption.d.ts +30 -0
  265. package/dist/nodes/process/VolumeAbsorption.d.ts.map +1 -0
  266. package/dist/nodes/process/VolumeAbsorption.js +36 -0
  267. package/dist/nodes/process/VolumeScatter.d.ts +31 -0
  268. package/dist/nodes/process/VolumeScatter.d.ts.map +1 -0
  269. package/dist/nodes/process/VolumeScatter.js +42 -0
  270. package/dist/nodes/process/VoronoiTexture.d.ts +38 -0
  271. package/dist/nodes/process/VoronoiTexture.d.ts.map +1 -0
  272. package/dist/nodes/process/VoronoiTexture.js +123 -0
  273. package/dist/nodes/process/WaveTexture.d.ts +39 -0
  274. package/dist/nodes/process/WaveTexture.d.ts.map +1 -0
  275. package/dist/nodes/process/WaveTexture.js +77 -0
  276. package/dist/nodes/process/Wavelength.d.ts +28 -0
  277. package/dist/nodes/process/Wavelength.d.ts.map +1 -0
  278. package/dist/nodes/process/Wavelength.js +43 -0
  279. package/dist/nodes/process/WhiteNoise.d.ts +27 -0
  280. package/dist/nodes/process/WhiteNoise.d.ts.map +1 -0
  281. package/dist/nodes/process/WhiteNoise.js +44 -0
  282. package/dist/nodes/shader/AmbientOcclusion.d.ts +47 -0
  283. package/dist/nodes/shader/AmbientOcclusion.d.ts.map +1 -0
  284. package/dist/nodes/shader/AmbientOcclusion.js +128 -0
  285. package/dist/nodes/shader/RayPortal.d.ts +57 -0
  286. package/dist/nodes/shader/RayPortal.d.ts.map +1 -0
  287. package/dist/nodes/shader/RayPortal.js +56 -0
  288. package/dist/shaders/color.d.ts +12 -0
  289. package/dist/shaders/color.d.ts.map +1 -0
  290. package/dist/shaders/color.js +42 -0
  291. package/dist/shaders/noise.d.ts +12 -0
  292. package/dist/shaders/noise.d.ts.map +1 -0
  293. package/dist/shaders/noise.js +70 -0
  294. package/dist/types/shader.d.ts +17 -0
  295. package/dist/types/shader.d.ts.map +1 -0
  296. package/dist/types/shader.js +1 -0
  297. package/package.json +44 -0
@@ -0,0 +1,75 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * Principled BSDF — Blender "Principled BSDF" node equivalent.
4
+ *
5
+ * Inputs: baseColor, metallic, roughness, ior, alpha, normal
6
+ * Outputs: BSDF (shader)
7
+ */
8
+ export class PrincipledBSDF extends ProcessNode {
9
+ get nodeType() { return 'PrincipledBSDF'; }
10
+ get metadata() {
11
+ return { label: 'Principled BSDF', category: 'Shader', color: '#336699', cost: 'medium', costNote: 'Schlick Fresnel + GGX — heavier on mobile.' };
12
+ }
13
+ constructor(inputs = {}) {
14
+ super('PrincipledBSDF');
15
+ this._inputs = this.createInputs(inputs, {
16
+ baseColor: ['color', '#ffffff'],
17
+ metallic: ['float', 0.0],
18
+ roughness: ['float', 0.5],
19
+ ior: ['float', 1.5],
20
+ alpha: ['float', 1.0],
21
+ normal: ['color', null],
22
+ });
23
+ this._outputs = this.createOutputs({ BSDF: 'shader' });
24
+ }
25
+ getInputSockets() { return this._inputs; }
26
+ getOutputSockets() { return this._outputs; }
27
+ compileDefs() { return this.glslFunction ?? PrincipledBSDF.glslFunction; }
28
+ compileCall(ctx) {
29
+ const normal = this._inputs.normal.isConnected()
30
+ ? ctx.outputVar(this._inputs.normal.connection.node, this._inputs.normal.connection.name)
31
+ : 'normalize(vNormal)';
32
+ return `vec3 ${ctx.outputVar(this, 'BSDF')} = _st_principledBSDF(${ctx.resolveInput(this._inputs.baseColor)}, ${ctx.resolveInput(this._inputs.metallic)}, ${ctx.resolveInput(this._inputs.roughness)}, ${ctx.resolveInput(this._inputs.ior)}, ${ctx.resolveInput(this._inputs.alpha)}, ${normal});`;
33
+ }
34
+ }
35
+ 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, float alpha, vec3 N) {
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;
75
+ }`;
@@ -0,0 +1,63 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ import type { NodeMetadata } from '../../core/ShaderNode.js';
3
+ import type { CompileContext } from '../../core/CompileContext.js';
4
+ import type { OutputSocket } from '../../core/OutputSocket.js';
5
+ export interface PrincipledHairInputs {
6
+ /** Base hair color. Blender: Color. */
7
+ color?: OutputSocket | string;
8
+ /** Longitudinal roughness — scattering along the strand axis. Blender: Roughness. */
9
+ roughness?: OutputSocket | number;
10
+ /** Azimuthal roughness — scattering around the strand. Blender: Radial Roughness. */
11
+ radialRoughness?: OutputSocket | number;
12
+ /** Clear-coat specular intensity. Blender: Coat. */
13
+ coat?: OutputSocket | number;
14
+ /** Index of refraction — affects R-lobe highlight color. Blender: IOR. */
15
+ ior?: OutputSocket | number;
16
+ /** Longitudinal shift of specular lobes. Blender: Offset. */
17
+ offset?: OutputSocket | number;
18
+ /** Per-strand color variation amount [0,1]. Blender: Random Color. */
19
+ randomColor?: OutputSocket | number;
20
+ /** Per-strand roughness variation amount [0,1]. Blender: Random Roughness. */
21
+ randomRoughness?: OutputSocket | number;
22
+ /** Random seed input — connect HairInfo.Random for per-strand variation. */
23
+ random?: OutputSocket | number;
24
+ }
25
+ /**
26
+ * Principled Hair BSDF — Blender "Principled Hair BSDF" node equivalent.
27
+ *
28
+ * Implements a Kajiya-Kay dual-lobe model suitable for real-time rendering:
29
+ * • Diffuse: sin(T, L) — angle between tangent and light
30
+ * • R lobe: primary specular highlight (white, sharp, IOR-tinted)
31
+ * • TRT lobe: secondary specular (colored, broader, offset in opposite direction)
32
+ * • Coat: clear-coat gloss on top
33
+ *
34
+ * Connect HairInfo.TangentNormal to the internal `tangent` socket and
35
+ * HairInfo.Random to `random` for correct per-strand behavior.
36
+ *
37
+ * Inputs: color, roughness, radialRoughness, coat, ior, offset,
38
+ * randomColor, randomRoughness, random, tangent
39
+ * Outputs: BSDF (shader)
40
+ */
41
+ export declare class PrincipledHair extends ProcessNode {
42
+ get nodeType(): string;
43
+ static instanceSpecificDef: boolean;
44
+ get metadata(): NodeMetadata;
45
+ static glslFunction: string;
46
+ private readonly _inputs;
47
+ private readonly _outputs;
48
+ constructor(inputs?: PrincipledHairInputs);
49
+ getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
50
+ getOutputSockets(): Record<string, OutputSocket>;
51
+ compileDefs(): string;
52
+ vertexInjections(): ({
53
+ attrName: string;
54
+ attrType: "vec3";
55
+ varyingName: string;
56
+ } | {
57
+ attrName: string;
58
+ attrType: "float";
59
+ varyingName: string;
60
+ })[];
61
+ compileCall(ctx: CompileContext): string;
62
+ }
63
+ //# sourceMappingURL=PrincipledHair.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrincipledHair.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/PrincipledHair.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,uCAAuC;IACvC,KAAK,CAAC,EAAa,YAAY,GAAG,MAAM,CAAA;IACxC,qFAAqF;IACrF,SAAS,CAAC,EAAS,YAAY,GAAG,MAAM,CAAA;IACxC,qFAAqF;IACrF,eAAe,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IACxC,oDAAoD;IACpD,IAAI,CAAC,EAAc,YAAY,GAAG,MAAM,CAAA;IACxC,0EAA0E;IAC1E,GAAG,CAAC,EAAe,YAAY,GAAG,MAAM,CAAA;IACxC,6DAA6D;IAC7D,MAAM,CAAC,EAAY,YAAY,GAAG,MAAM,CAAA;IACxC,sEAAsE;IACtE,WAAW,CAAC,EAAO,YAAY,GAAG,MAAM,CAAA;IACxC,8EAA8E;IAC9E,eAAe,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IACxC,4EAA4E;IAC5E,MAAM,CAAC,EAAY,YAAY,GAAG,MAAM,CAAA;CACzC;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC7C,IAAI,QAAQ,WAA8B;IAC1C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAGD,MAAM,CAAC,YAAY,SAsEnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,oBAAyB;IAiB7C,eAAe;IACf,gBAAgB;IAChB,WAAW;IAGX,gBAAgB;;;;;;;;;IAOhB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAgBzC"}
@@ -0,0 +1,137 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * Principled Hair BSDF — Blender "Principled Hair BSDF" node equivalent.
4
+ *
5
+ * Implements a Kajiya-Kay dual-lobe model suitable for real-time rendering:
6
+ * • Diffuse: sin(T, L) — angle between tangent and light
7
+ * • R lobe: primary specular highlight (white, sharp, IOR-tinted)
8
+ * • TRT lobe: secondary specular (colored, broader, offset in opposite direction)
9
+ * • Coat: clear-coat gloss on top
10
+ *
11
+ * Connect HairInfo.TangentNormal to the internal `tangent` socket and
12
+ * HairInfo.Random to `random` for correct per-strand behavior.
13
+ *
14
+ * Inputs: color, roughness, radialRoughness, coat, ior, offset,
15
+ * randomColor, randomRoughness, random, tangent
16
+ * Outputs: BSDF (shader)
17
+ */
18
+ export class PrincipledHair extends ProcessNode {
19
+ get nodeType() { return 'PrincipledHair'; }
20
+ get metadata() {
21
+ return { label: 'Principled Hair BSDF', category: 'Shader', color: '#5a3a1a', cost: 'medium' };
22
+ }
23
+ constructor(inputs = {}) {
24
+ super('PrincipledHair');
25
+ this._inputs = this.createInputs(inputs, {
26
+ color: ['color', inputs.color ?? '#8b6050'],
27
+ roughness: ['float', inputs.roughness ?? 0.3],
28
+ radialRoughness: ['float', inputs.radialRoughness ?? 0.5],
29
+ coat: ['float', inputs.coat ?? 0.2],
30
+ ior: ['float', inputs.ior ?? 1.55],
31
+ offset: ['float', inputs.offset ?? 0.04],
32
+ randomColor: ['float', inputs.randomColor ?? 0.1],
33
+ randomRoughness: ['float', inputs.randomRoughness ?? 0.0],
34
+ random: ['float', inputs.random ?? 0.0],
35
+ tangent: ['color', null],
36
+ });
37
+ this._outputs = this.createOutputs({ BSDF: 'shader' });
38
+ }
39
+ getInputSockets() { return this._inputs; }
40
+ getOutputSockets() { return this._outputs; }
41
+ compileDefs() { return PrincipledHair.glslFunction; }
42
+ // Ensure strandTangent is always available even without HairInfo in the graph
43
+ vertexInjections() {
44
+ return [
45
+ { attrName: 'strandTangent', attrType: 'vec3', varyingName: 'vStrandTangent' },
46
+ { attrName: 'strandRandom', attrType: 'float', varyingName: 'vStrandRandom' },
47
+ ];
48
+ }
49
+ compileCall(ctx) {
50
+ const color = ctx.resolveInput(this._inputs.color);
51
+ const roughness = ctx.resolveInput(this._inputs.roughness);
52
+ const radialRoughness = ctx.resolveInput(this._inputs.radialRoughness);
53
+ const coat = ctx.resolveInput(this._inputs.coat);
54
+ const ior = ctx.resolveInput(this._inputs.ior);
55
+ const offset = ctx.resolveInput(this._inputs.offset);
56
+ const randomColor = ctx.resolveInput(this._inputs.randomColor);
57
+ const randomRoughness = ctx.resolveInput(this._inputs.randomRoughness);
58
+ const random = ctx.resolveInput(this._inputs.random);
59
+ const tangent = this._inputs.tangent.isConnected()
60
+ ? ctx.outputVar(this._inputs.tangent.connection.node, this._inputs.tangent.connection.name)
61
+ : 'normalize(vStrandTangent)'; // fallback: read attribute directly if not connected
62
+ return `vec3 ${ctx.outputVar(this, 'BSDF')} = _st_principledHair(${color}, ${roughness}, ${radialRoughness}, ${coat}, ${ior}, ${offset}, ${randomColor}, ${randomRoughness}, ${random}, ${tangent});`;
63
+ }
64
+ }
65
+ PrincipledHair.instanceSpecificDef = false;
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;
137
+ }`;
@@ -0,0 +1,37 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ import type { NodeMetadata } from '../../core/ShaderNode.js';
3
+ import type { CompileContext } from '../../core/CompileContext.js';
4
+ import type { OutputSocket } from '../../core/OutputSocket.js';
5
+ export interface PrincipledVolumeInputs {
6
+ color?: OutputSocket | string;
7
+ density?: OutputSocket | number;
8
+ anisotropy?: OutputSocket | number;
9
+ absorptionColor?: OutputSocket | string;
10
+ emissionColor?: OutputSocket | string;
11
+ emissionStrength?: OutputSocket | number;
12
+ blackbodyIntensity?: OutputSocket | number;
13
+ temperature?: OutputSocket | number;
14
+ }
15
+ /**
16
+ * Principled Volume — Blender "Principled Volume" shader node.
17
+ * Combines scatter, absorption, and emission into a single volume shader.
18
+ * Connect to MaterialOutput.volume.
19
+ *
20
+ * Inputs: color, density, anisotropy, absorptionColor, emissionColor,
21
+ * emissionStrength, blackbodyIntensity, temperature
22
+ * Outputs: Volume (shader)
23
+ */
24
+ export declare class PrincipledVolume extends ProcessNode {
25
+ get nodeType(): string;
26
+ static instanceSpecificDef: boolean;
27
+ get metadata(): NodeMetadata;
28
+ static glslFunction: string;
29
+ private readonly _inputs;
30
+ private readonly _outputs;
31
+ constructor(inputs?: PrincipledVolumeInputs);
32
+ getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
33
+ getOutputSockets(): Record<string, OutputSocket>;
34
+ compileDefs(): string;
35
+ compileCall(ctx: CompileContext): string;
36
+ }
37
+ //# sourceMappingURL=PrincipledVolume.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrincipledVolume.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/PrincipledVolume.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,sBAAsB;IACrC,KAAK,CAAC,EAAc,YAAY,GAAG,MAAM,CAAA;IACzC,OAAO,CAAC,EAAY,YAAY,GAAG,MAAM,CAAA;IACzC,UAAU,CAAC,EAAS,YAAY,GAAG,MAAM,CAAA;IACzC,eAAe,CAAC,EAAI,YAAY,GAAG,MAAM,CAAA;IACzC,aAAa,CAAC,EAAM,YAAY,GAAG,MAAM,CAAA;IACzC,gBAAgB,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IACzC,kBAAkB,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;IAC1C,WAAW,CAAC,EAAQ,YAAY,GAAG,MAAM,CAAA;CAC1C;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,IAAI,QAAQ,WAAgC;IAC5C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAqBnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,sBAA2B;IAe/C,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAWzC"}
@@ -0,0 +1,67 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * Principled Volume — Blender "Principled Volume" shader node.
4
+ * Combines scatter, absorption, and emission into a single volume shader.
5
+ * Connect to MaterialOutput.volume.
6
+ *
7
+ * Inputs: color, density, anisotropy, absorptionColor, emissionColor,
8
+ * emissionStrength, blackbodyIntensity, temperature
9
+ * Outputs: Volume (shader)
10
+ */
11
+ export class PrincipledVolume extends ProcessNode {
12
+ get nodeType() { return 'PrincipledVolume'; }
13
+ get metadata() {
14
+ return { label: 'Principled Volume', category: 'Shader', color: '#1a6688', cost: 'high' };
15
+ }
16
+ constructor(inputs = {}) {
17
+ super('PrincipledVolume');
18
+ this._inputs = this.createInputs(inputs, {
19
+ color: ['color', '#ffffff'],
20
+ density: ['float', inputs.density ?? 1.0],
21
+ anisotropy: ['float', inputs.anisotropy ?? 0.0],
22
+ absorptionColor: ['color', '#000000'],
23
+ emissionColor: ['color', '#000000'],
24
+ emissionStrength: ['float', inputs.emissionStrength ?? 0.0],
25
+ blackbodyIntensity: ['float', inputs.blackbodyIntensity ?? 0.0],
26
+ temperature: ['float', inputs.temperature ?? 1000.0],
27
+ });
28
+ this._outputs = this.createOutputs({ Volume: 'shader' });
29
+ }
30
+ getInputSockets() { return this._inputs; }
31
+ getOutputSockets() { return this._outputs; }
32
+ compileDefs() { return PrincipledVolume.glslFunction; }
33
+ compileCall(ctx) {
34
+ const color = ctx.resolveInput(this._inputs.color);
35
+ const density = ctx.resolveInput(this._inputs.density);
36
+ const anisotropy = ctx.resolveInput(this._inputs.anisotropy);
37
+ const absorptionColor = ctx.resolveInput(this._inputs.absorptionColor);
38
+ const emissionColor = ctx.resolveInput(this._inputs.emissionColor);
39
+ const emissionStrength = ctx.resolveInput(this._inputs.emissionStrength);
40
+ const blackbodyIntensity = ctx.resolveInput(this._inputs.blackbodyIntensity);
41
+ const temperature = ctx.resolveInput(this._inputs.temperature);
42
+ return `vec3 ${ctx.outputVar(this, 'Volume')} = _st_principledVolume(${color}, ${density}, ${anisotropy}, ${absorptionColor}, ${emissionColor}, ${emissionStrength}, ${blackbodyIntensity}, ${temperature});`;
43
+ }
44
+ }
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;
67
+ }`;
@@ -0,0 +1,45 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ import type { NodeMetadata } from '../../core/ShaderNode.js';
3
+ import type { CompileContext } from '../../core/CompileContext.js';
4
+ import type { OutputSocket } from '../../core/OutputSocket.js';
5
+ /** A curve point [x, y] where both x and y are in [0, 1]. */
6
+ export type CurvePoint = [number, number];
7
+ export interface RGBCurvesInputs {
8
+ color?: OutputSocket | string;
9
+ fac?: OutputSocket | number;
10
+ /**
11
+ * Per-channel piecewise linear curve as [[x,y], ...] control points.
12
+ * Points are sorted by x automatically. Default = identity [[0,0],[1,1]].
13
+ */
14
+ rPoints?: CurvePoint[];
15
+ gPoints?: CurvePoint[];
16
+ bPoints?: CurvePoint[];
17
+ /** Master curve applied after per-channel curves. Default = identity. */
18
+ masterPoints?: CurvePoint[];
19
+ }
20
+ /**
21
+ * RGB Curves — Blender "RGB Curves" node equivalent.
22
+ * Full piecewise linear curve per channel (R, G, B) plus a master curve.
23
+ * Matches Blender's RGB Curves node exactly — arbitrary control points,
24
+ * piecewise linear interpolation between them.
25
+ *
26
+ * Inputs: color, fac
27
+ * Outputs: Color (color)
28
+ */
29
+ export declare class RGBCurves extends ProcessNode {
30
+ get nodeType(): string;
31
+ static instanceSpecificDef: boolean;
32
+ get metadata(): NodeMetadata;
33
+ private readonly rPts;
34
+ private readonly gPts;
35
+ private readonly bPts;
36
+ private readonly mPts;
37
+ private readonly _inputs;
38
+ private readonly _outputs;
39
+ constructor(inputs?: RGBCurvesInputs);
40
+ getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
41
+ getOutputSockets(): Record<string, OutputSocket>;
42
+ compileDefs(): string;
43
+ compileCall(ctx: CompileContext): string;
44
+ }
45
+ //# sourceMappingURL=RGBCurves.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RGBCurves.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/RGBCurves.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,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEzC,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAG,YAAY,GAAG,MAAM,CAAA;IAC9B,GAAG,CAAC,EAAK,YAAY,GAAG,MAAM,CAAA;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,yEAAyE;IACzE,YAAY,CAAC,EAAE,UAAU,EAAE,CAAA;CAC5B;AAED;;;;;;;;GAQG;AACH,qBAAa,SAAU,SAAQ,WAAW;IACxC,IAAI,QAAQ,WAAyB;IACrC,MAAM,CAAC,mBAAmB,UAAO;IAEjC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,eAAoB;IAcxC,eAAe;IACf,gBAAgB;IAEhB,WAAW,IAAI,MAAM;IAUrB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAkBzC"}
@@ -0,0 +1,81 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * RGB Curves — Blender "RGB Curves" node equivalent.
4
+ * Full piecewise linear curve per channel (R, G, B) plus a master curve.
5
+ * Matches Blender's RGB Curves node exactly — arbitrary control points,
6
+ * piecewise linear interpolation between them.
7
+ *
8
+ * Inputs: color, fac
9
+ * Outputs: Color (color)
10
+ */
11
+ export class RGBCurves extends ProcessNode {
12
+ get nodeType() { return 'RGBCurves'; }
13
+ get metadata() {
14
+ return { label: 'RGB Curves', category: 'Color', color: '#633060', cost: 'low' };
15
+ }
16
+ constructor(inputs = {}) {
17
+ super('RGBCurves');
18
+ const identity = [[0, 0], [1, 1]];
19
+ this.rPts = sortPoints(inputs.rPoints ?? identity);
20
+ this.gPts = sortPoints(inputs.gPoints ?? identity);
21
+ this.bPts = sortPoints(inputs.bPoints ?? identity);
22
+ this.mPts = sortPoints(inputs.masterPoints ?? identity);
23
+ this._inputs = this.createInputs(inputs, {
24
+ color: ['color', '#ffffff'],
25
+ fac: ['float', inputs.fac ?? 1.0],
26
+ });
27
+ this._outputs = this.createOutputs({ Color: 'color' });
28
+ }
29
+ getInputSockets() { return this._inputs; }
30
+ getOutputSockets() { return this._outputs; }
31
+ compileDefs() {
32
+ // Emit one piecewise linear evaluator function per curve per instance
33
+ return [
34
+ buildCurveFn(`_rc_r_${this.id}`, this.rPts),
35
+ buildCurveFn(`_rc_g_${this.id}`, this.gPts),
36
+ buildCurveFn(`_rc_b_${this.id}`, this.bPts),
37
+ buildCurveFn(`_rc_m_${this.id}`, this.mPts),
38
+ ].join('\n');
39
+ }
40
+ compileCall(ctx) {
41
+ const col = ctx.resolveInput(this._inputs.color);
42
+ const fac = ctx.resolveInput(this._inputs.fac);
43
+ const id = this.id;
44
+ const out = ctx.outputVar(this, 'Color');
45
+ return [
46
+ `vec3 _rc_${id} = ${col};`,
47
+ // Per-channel curves
48
+ `_rc_${id}.r = _rc_r_${id}(_rc_${id}.r);`,
49
+ `_rc_${id}.g = _rc_g_${id}(_rc_${id}.g);`,
50
+ `_rc_${id}.b = _rc_b_${id}(_rc_${id}.b);`,
51
+ // Master curve applied to each channel
52
+ `_rc_${id}.r = _rc_m_${id}(_rc_${id}.r);`,
53
+ `_rc_${id}.g = _rc_m_${id}(_rc_${id}.g);`,
54
+ `_rc_${id}.b = _rc_m_${id}(_rc_${id}.b);`,
55
+ `vec3 ${out} = mix(${col}, clamp(_rc_${id}, 0.0, 1.0), clamp(${fac}, 0.0, 1.0));`,
56
+ ].join('\n ');
57
+ }
58
+ }
59
+ RGBCurves.instanceSpecificDef = true;
60
+ // ── helpers ───────────────────────────────────────────────────────────────────
61
+ function sortPoints(pts) {
62
+ return [...pts].sort((a, b) => a[0] - b[0]);
63
+ }
64
+ function buildCurveFn(name, pts) {
65
+ // No array initializers — GLSL ES 1.00 doesn't support float[n](...) syntax.
66
+ // Generate a fully unrolled if/else chain with all values baked as literals.
67
+ const f = (n) => n.toFixed(5);
68
+ const clamps = `
69
+ if (t <= ${f(pts[0][0])}) return ${f(pts[0][1])};
70
+ if (t >= ${f(pts[pts.length - 1][0])}) return ${f(pts[pts.length - 1][1])};`;
71
+ const segments = pts.slice(0, -1).map((p, i) => {
72
+ const x0 = f(p[0]), y0 = f(p[1]);
73
+ const x1 = f(pts[i + 1][0]), y1 = f(pts[i + 1][1]);
74
+ return ` if (t <= ${x1}) return mix(${y0}, ${y1}, (t - ${x0}) / (${x1} - ${x0}));`;
75
+ }).join('\n');
76
+ return `
77
+ float ${name}(float t) {${clamps}
78
+ ${segments}
79
+ return ${f(pts[pts.length - 1][1])};
80
+ }`;
81
+ }
@@ -0,0 +1,28 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ import type { NodeMetadata } from '../../core/ShaderNode.js';
3
+ import type { CompileContext } from '../../core/CompileContext.js';
4
+ import type { OutputSocket } from '../../core/OutputSocket.js';
5
+ export interface RGBtoBWInputs {
6
+ color?: OutputSocket | string;
7
+ }
8
+ /**
9
+ * RGB to BW — Blender "RGB to BW" node equivalent.
10
+ * Converts a colour to a greyscale float using luminance weights.
11
+ *
12
+ * Inputs: color (color)
13
+ * Outputs: Val (float) — luminance value [0-1]
14
+ */
15
+ export declare class RGBtoBW extends ProcessNode {
16
+ get nodeType(): string;
17
+ static instanceSpecificDef: boolean;
18
+ get metadata(): NodeMetadata;
19
+ static glslFunction: string;
20
+ private readonly _inputs;
21
+ private readonly _outputs;
22
+ constructor(inputs?: RGBtoBWInputs);
23
+ getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
24
+ getOutputSockets(): Record<string, OutputSocket>;
25
+ compileDefs(): string;
26
+ compileCall(ctx: CompileContext): string;
27
+ }
28
+ //# sourceMappingURL=RGBtoBW.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RGBtoBW.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/RGBtoBW.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,aAAa;IAC5B,KAAK,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;CAC9B;AAED;;;;;;GAMG;AACH,qBAAa,OAAQ,SAAQ,WAAW;IACtC,IAAI,QAAQ,WAAuB;IACnC,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAGnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,aAAkB;IAMtC,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAIzC"}
@@ -0,0 +1,31 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * RGB to BW — Blender "RGB to BW" node equivalent.
4
+ * Converts a colour to a greyscale float using luminance weights.
5
+ *
6
+ * Inputs: color (color)
7
+ * Outputs: Val (float) — luminance value [0-1]
8
+ */
9
+ export class RGBtoBW extends ProcessNode {
10
+ get nodeType() { return 'RGBtoBW'; }
11
+ get metadata() {
12
+ return { label: 'RGB to BW', category: 'Converter', color: '#4a3a6a', cost: 'low' };
13
+ }
14
+ constructor(inputs = {}) {
15
+ super('RGBtoBW');
16
+ this._inputs = this.createInputs(inputs, { color: ['color', '#ffffff'] });
17
+ this._outputs = this.createOutputs({ Val: 'float' });
18
+ }
19
+ getInputSockets() { return this._inputs; }
20
+ getOutputSockets() { return this._outputs; }
21
+ compileDefs() { return RGBtoBW.glslFunction; }
22
+ compileCall(ctx) {
23
+ const col = ctx.resolveInput(this._inputs.color);
24
+ return `float ${ctx.outputVar(this, 'Val')} = _st_rgbToBw(${col});`;
25
+ }
26
+ }
27
+ RGBtoBW.instanceSpecificDef = false;
28
+ RGBtoBW.glslFunction = `
29
+ float _st_rgbToBw(vec3 col) {
30
+ return dot(col, vec3(0.2126, 0.7152, 0.0722));
31
+ }`;
@@ -0,0 +1,32 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ import type { NodeMetadata } from '../../core/ShaderNode.js';
3
+ import type { CompileContext } from '../../core/CompileContext.js';
4
+ import type { OutputSocket } from '../../core/OutputSocket.js';
5
+ export interface RefractionBSDFInputs {
6
+ color?: OutputSocket | string;
7
+ roughness?: OutputSocket | number;
8
+ ior?: OutputSocket | number;
9
+ normal?: OutputSocket;
10
+ }
11
+ /**
12
+ * Refraction BSDF — Blender "Refraction BSDF" node equivalent.
13
+ * Simulates light bending through a transparent medium.
14
+ * Approximated in real-time using a tinted transmission colour.
15
+ *
16
+ * Inputs: color, roughness, ior, normal
17
+ * Outputs: BSDF (shader)
18
+ */
19
+ export declare class RefractionBSDF extends ProcessNode {
20
+ get nodeType(): string;
21
+ static instanceSpecificDef: boolean;
22
+ get metadata(): NodeMetadata;
23
+ static glslFunction: string;
24
+ private readonly _inputs;
25
+ private readonly _outputs;
26
+ constructor(inputs?: RefractionBSDFInputs);
27
+ getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
28
+ getOutputSockets(): Record<string, OutputSocket>;
29
+ compileDefs(): string;
30
+ compileCall(ctx: CompileContext): string;
31
+ }
32
+ //# sourceMappingURL=RefractionBSDF.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RefractionBSDF.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/RefractionBSDF.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,KAAK,CAAC,EAAM,YAAY,GAAG,MAAM,CAAA;IACjC,SAAS,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;IACjC,GAAG,CAAC,EAAQ,YAAY,GAAG,MAAM,CAAA;IACjC,MAAM,CAAC,EAAK,YAAY,CAAA;CACzB;AAED;;;;;;;GAOG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC7C,IAAI,QAAQ,WAA8B;IAC1C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAOnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,oBAAyB;IAW7C,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CASzC"}