@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,42 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * Volume Scatter — Blender "Volume Scatter" shader node.
4
+ * Scatters light inside the volume with Henyey-Greenstein phase function.
5
+ * Connect to MaterialOutput.volume.
6
+ *
7
+ * Inputs: color (color), density (float), anisotropy (float, -1..1)
8
+ * Outputs: Volume (shader)
9
+ */
10
+ export class VolumeScatter extends ProcessNode {
11
+ get nodeType() { return 'VolumeScatter'; }
12
+ get metadata() {
13
+ return { label: 'Volume Scatter', category: 'Shader', color: '#3388cc', cost: 'medium' };
14
+ }
15
+ constructor(inputs = {}) {
16
+ super('VolumeScatter');
17
+ this._inputs = this.createInputs(inputs, {
18
+ color: ['color', '#ffffff'],
19
+ density: ['float', inputs.density ?? 1.0],
20
+ anisotropy: ['float', inputs.anisotropy ?? 0.0],
21
+ });
22
+ this._outputs = this.createOutputs({ Volume: 'shader' });
23
+ }
24
+ getInputSockets() { return this._inputs; }
25
+ getOutputSockets() { return this._outputs; }
26
+ compileDefs() { return VolumeScatter.glslFunction; }
27
+ compileCall(ctx) {
28
+ const color = ctx.resolveInput(this._inputs.color);
29
+ const density = ctx.resolveInput(this._inputs.density);
30
+ const anisotropy = ctx.resolveInput(this._inputs.anisotropy);
31
+ return `vec3 ${ctx.outputVar(this, 'Volume')} = _st_volumeScatter(${color}, ${density}, ${anisotropy});`;
32
+ }
33
+ }
34
+ VolumeScatter.instanceSpecificDef = false;
35
+ VolumeScatter.glslFunction = `
36
+ vec3 _st_volumeScatter(vec3 color, float density, float anisotropy) {
37
+ float g = clamp(anisotropy, -0.9999, 0.9999);
38
+ float g2 = g * g;
39
+ // HG phase at cosTheta=0 (isotropic approximation for surface shading context)
40
+ float phase = (1.0 - g2) / pow(1.0 + g2, 1.5);
41
+ return color * density * phase;
42
+ }`;
@@ -0,0 +1,38 @@
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 type VoronoiFeature = 'F1' | 'F2' | 'SMOOTH_F1' | 'DISTANCE_TO_EDGE';
6
+ export interface VoronoiTextureInputs {
7
+ vector?: OutputSocket;
8
+ scale?: number | OutputSocket;
9
+ smoothness?: number | OutputSocket;
10
+ feature?: VoronoiFeature;
11
+ }
12
+ /**
13
+ * Voronoi Texture — Blender "Voronoi Texture" node equivalent.
14
+ * Full implementation matching all four Blender feature modes:
15
+ *
16
+ * F1 — distance to nearest cell center (classic Voronoi)
17
+ * F2 — distance to second-nearest cell center
18
+ * SMOOTH_F1 — smooth minimum of F1 across cells (softens cell edges)
19
+ * DISTANCE_TO_EDGE — distance to the Voronoi cell boundary
20
+ *
21
+ * Inputs: vector, scale (float), smoothness (float, used by SMOOTH_F1)
22
+ * Outputs: Distance (float), Color (color)
23
+ */
24
+ export declare class VoronoiTexture extends ProcessNode {
25
+ get nodeType(): string;
26
+ static instanceSpecificDef: boolean;
27
+ get metadata(): NodeMetadata;
28
+ static glslFunction: string;
29
+ private readonly feature;
30
+ private readonly _inputs;
31
+ private readonly _outputs;
32
+ constructor(inputs?: VoronoiTextureInputs);
33
+ getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
34
+ getOutputSockets(): Record<string, OutputSocket>;
35
+ compileDefs(): string;
36
+ compileCall(ctx: CompileContext): string;
37
+ }
38
+ //# sourceMappingURL=VoronoiTexture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoronoiTexture.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/VoronoiTexture.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,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,WAAW,GAAG,kBAAkB,CAAA;AAE3E,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAM,YAAY,CAAA;IACzB,KAAK,CAAC,EAAO,MAAM,GAAG,YAAY,CAAA;IAClC,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;IAClC,OAAO,CAAC,EAAK,cAAc,CAAA;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC7C,IAAI,QAAQ,WAA8B;IAC1C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAQ3B;IAED,MAAM,CAAC,YAAY,SAgDnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,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;CAuCzC"}
@@ -0,0 +1,123 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * Voronoi Texture — Blender "Voronoi Texture" node equivalent.
4
+ * Full implementation matching all four Blender feature modes:
5
+ *
6
+ * F1 — distance to nearest cell center (classic Voronoi)
7
+ * F2 — distance to second-nearest cell center
8
+ * SMOOTH_F1 — smooth minimum of F1 across cells (softens cell edges)
9
+ * DISTANCE_TO_EDGE — distance to the Voronoi cell boundary
10
+ *
11
+ * Inputs: vector, scale (float), smoothness (float, used by SMOOTH_F1)
12
+ * Outputs: Distance (float), Color (color)
13
+ */
14
+ export class VoronoiTexture extends ProcessNode {
15
+ get nodeType() { return 'VoronoiTexture'; }
16
+ get metadata() {
17
+ return {
18
+ label: 'Voronoi Texture',
19
+ category: 'Texture',
20
+ color: '#3a6b3a',
21
+ cost: 'high',
22
+ costNote: '3×3×3 cell loop per fragment — avoid stacking.',
23
+ };
24
+ }
25
+ constructor(inputs = {}) {
26
+ super('VoronoiTexture');
27
+ this.feature = inputs.feature ?? 'F1';
28
+ this._inputs = this.createInputs(inputs, {
29
+ vector: ['color', null],
30
+ scale: ['float', inputs.scale ?? 5.0],
31
+ smoothness: ['float', inputs.smoothness ?? 1.0],
32
+ });
33
+ this._outputs = this.createOutputs({ Distance: 'float', Color: 'color' });
34
+ }
35
+ getInputSockets() { return this._inputs; }
36
+ getOutputSockets() { return this._outputs; }
37
+ compileDefs() { return VoronoiTexture.glslFunction; }
38
+ compileCall(ctx) {
39
+ const p = this._inputs.vector.isConnected()
40
+ ? `(${ctx.outputVar(this._inputs.vector.connection.node, this._inputs.vector.connection.name)} * ${ctx.resolveInput(this._inputs.scale)})`
41
+ : `(vec3(vUv, 0.0) * ${ctx.resolveInput(this._inputs.scale)})`;
42
+ const smooth = ctx.resolveInput(this._inputs.smoothness);
43
+ const dv = ctx.outputVar(this, 'Distance');
44
+ const cv = ctx.outputVar(this, 'Color');
45
+ const tmp = `_vor_${this.id}`;
46
+ switch (this.feature) {
47
+ case 'F2':
48
+ return [
49
+ `vec3 ${tmp}_col = vec3(0.0);`,
50
+ `vec2 ${tmp}_f = _st_vorF1F2(${p}, ${tmp}_col);`,
51
+ `float ${dv} = ${tmp}_f.y;`,
52
+ `vec3 ${cv} = ${tmp}_col;`,
53
+ ].join('\n ');
54
+ case 'SMOOTH_F1':
55
+ return [
56
+ `float ${dv} = _st_vorSmoothF1(${p}, ${smooth});`,
57
+ `vec3 ${cv} = vec3(${dv});`,
58
+ ].join('\n ');
59
+ case 'DISTANCE_TO_EDGE':
60
+ return [
61
+ `float ${dv} = _st_vorDistToEdge(${p});`,
62
+ `vec3 ${cv} = vec3(${dv});`,
63
+ ].join('\n ');
64
+ default: // F1
65
+ return [
66
+ `vec3 ${tmp}_col = vec3(0.0);`,
67
+ `vec2 ${tmp}_f = _st_vorF1F2(${p}, ${tmp}_col);`,
68
+ `float ${dv} = ${tmp}_f.x;`,
69
+ `vec3 ${cv} = ${tmp}_col;`,
70
+ ].join('\n ');
71
+ }
72
+ }
73
+ }
74
+ VoronoiTexture.instanceSpecificDef = false;
75
+ VoronoiTexture.glslFunction = `
76
+ vec3 _st_vorHash(vec3 cell) {
77
+ return fract(sin(vec3(
78
+ dot(cell, vec3(127.1, 311.7, 74.7)),
79
+ dot(cell, vec3(269.5, 183.3, 246.1)),
80
+ dot(cell, vec3(113.5, 271.9, 124.6))
81
+ )) * 43758.5453);
82
+ }
83
+
84
+ // Returns vec3(f1_dist, f2_dist, 0) and outputs cell color via out param
85
+ vec2 _st_vorF1F2(vec3 p, out vec3 cellColor) {
86
+ vec3 pi = floor(p), pf = fract(p);
87
+ float d1 = 8.0, d2 = 8.0;
88
+ vec3 c1 = vec3(0.0);
89
+ for (int x = -1; x <= 1; x++)
90
+ for (int y = -1; y <= 1; y++)
91
+ for (int z = -1; z <= 1; z++) {
92
+ vec3 nb = vec3(float(x), float(y), float(z));
93
+ vec3 pt = _st_vorHash(pi + nb);
94
+ float dist = length(nb + pt - pf);
95
+ if (dist < d1) { d2 = d1; d1 = dist; c1 = pt; }
96
+ else if (dist < d2) { d2 = dist; }
97
+ }
98
+ cellColor = c1;
99
+ return vec2(d1, d2);
100
+ }
101
+
102
+ float _st_vorSmoothF1(vec3 p, float smoothness) {
103
+ vec3 pi = floor(p), pf = fract(p);
104
+ float res = 0.0;
105
+ float k = max(smoothness, 0.0001);
106
+ for (int x = -1; x <= 1; x++)
107
+ for (int y = -1; y <= 1; y++)
108
+ for (int z = -1; z <= 1; z++) {
109
+ vec3 nb = vec3(float(x), float(y), float(z));
110
+ vec3 pt = _st_vorHash(pi + nb);
111
+ float dist = length(nb + pt - pf);
112
+ res += exp(-32.0 * dist / k);
113
+ }
114
+ return -(k / 32.0) * log(res);
115
+ }
116
+
117
+ float _st_vorDistToEdge(vec3 p) {
118
+ // Approximate distance to cell edge as (F2 - F1) * 0.5.
119
+ // Avoids the 5x5x5 loop that exceeds WebGL1 loop-unroll limits.
120
+ vec3 col = vec3(0.0);
121
+ vec2 f = _st_vorF1F2(p, col);
122
+ return (f.y - f.x) * 0.5;
123
+ }`;
@@ -0,0 +1,39 @@
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 type WaveType = 'BANDS' | 'RINGS';
6
+ export type WaveProfile = 'SINE' | 'SAW' | 'TRIANGLE';
7
+ export interface WaveTextureInputs {
8
+ vector?: OutputSocket;
9
+ scale?: number | OutputSocket;
10
+ distortion?: number | OutputSocket;
11
+ detail?: number | OutputSocket;
12
+ detailScale?: number | OutputSocket;
13
+ detailRoughness?: number | OutputSocket;
14
+ waveType?: WaveType;
15
+ profile?: WaveProfile;
16
+ }
17
+ /**
18
+ * Wave Texture — Blender "Wave Texture" node equivalent.
19
+ * Generates stripe/ring patterns with optional noise distortion.
20
+ *
21
+ * Inputs: vector, scale, distortion, detail, detailScale, detailRoughness
22
+ * Outputs: Color (color), Fac (float)
23
+ */
24
+ export declare class WaveTexture extends ProcessNode {
25
+ get nodeType(): string;
26
+ static instanceSpecificDef: boolean;
27
+ get metadata(): NodeMetadata;
28
+ static glslFunction: string;
29
+ private readonly waveType;
30
+ private readonly profile;
31
+ private readonly _inputs;
32
+ private readonly _outputs;
33
+ constructor(inputs?: WaveTextureInputs);
34
+ getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
35
+ getOutputSockets(): Record<string, OutputSocket>;
36
+ compileDefs(): string;
37
+ compileCall(ctx: CompileContext): string;
38
+ }
39
+ //# sourceMappingURL=WaveTexture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WaveTexture.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/WaveTexture.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,MAAM,QAAQ,GAAK,OAAO,GAAG,OAAO,CAAA;AAC1C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,CAAA;AAErD,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAO,YAAY,CAAA;IAC1B,KAAK,CAAC,EAAQ,MAAM,GAAG,YAAY,CAAA;IACnC,UAAU,CAAC,EAAG,MAAM,GAAG,YAAY,CAAA;IACnC,MAAM,CAAC,EAAO,MAAM,GAAG,YAAY,CAAA;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;IACnC,eAAe,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;IACvC,QAAQ,CAAC,EAAK,QAAQ,CAAA;IACtB,OAAO,CAAC,EAAM,WAAW,CAAA;CAC1B;AAED;;;;;;GAMG;AACH,qBAAa,WAAY,SAAQ,WAAW;IAC1C,IAAI,QAAQ,WAA2B;IACvC,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SA0BnB;IAEA,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,iBAAsB;IAe1C,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAkBzC"}
@@ -0,0 +1,77 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * Wave Texture — Blender "Wave Texture" node equivalent.
4
+ * Generates stripe/ring patterns with optional noise distortion.
5
+ *
6
+ * Inputs: vector, scale, distortion, detail, detailScale, detailRoughness
7
+ * Outputs: Color (color), Fac (float)
8
+ */
9
+ export class WaveTexture extends ProcessNode {
10
+ get nodeType() { return 'WaveTexture'; }
11
+ get metadata() {
12
+ return { label: 'Wave Texture', category: 'Texture', color: '#3a6b3a', cost: 'medium' };
13
+ }
14
+ constructor(inputs = {}) {
15
+ super('WaveTexture');
16
+ this.waveType = inputs.waveType ?? 'BANDS';
17
+ this.profile = inputs.profile ?? 'SINE';
18
+ this._inputs = this.createInputs(inputs, {
19
+ vector: ['color', null],
20
+ scale: ['float', inputs.scale ?? 5.0],
21
+ distortion: ['float', inputs.distortion ?? 0.0],
22
+ detail: ['float', inputs.detail ?? 2.0],
23
+ detailScale: ['float', inputs.detailScale ?? 1.0],
24
+ detailRoughness: ['float', inputs.detailRoughness ?? 0.5],
25
+ });
26
+ this._outputs = this.createOutputs({ Color: 'color', Fac: 'float' });
27
+ }
28
+ getInputSockets() { return this._inputs; }
29
+ getOutputSockets() { return this._outputs; }
30
+ compileDefs() { return WaveTexture.glslFunction; }
31
+ compileCall(ctx) {
32
+ const vec = this._inputs.vector.isConnected()
33
+ ? `vec3(${ctx.outputVar(this._inputs.vector.connection.node, this._inputs.vector.connection.name)})`
34
+ : 'vec3(vUv, 0.0)';
35
+ const s = ctx.resolveInput(this._inputs.scale);
36
+ const d = ctx.resolveInput(this._inputs.distortion);
37
+ const det = ctx.resolveInput(this._inputs.detail);
38
+ const ds = ctx.resolveInput(this._inputs.detailScale);
39
+ const dr = ctx.resolveInput(this._inputs.detailRoughness);
40
+ const wt = this.waveType === 'BANDS' ? 0 : 1;
41
+ const pf = this.profile === 'SINE' ? 0 : this.profile === 'SAW' ? 1 : 2;
42
+ const fv = ctx.outputVar(this, 'Fac');
43
+ const cv = ctx.outputVar(this, 'Color');
44
+ return [
45
+ `float ${fv} = _st_waveTexture(${vec}, ${s}, ${d}, ${det}, ${ds}, ${dr}, ${wt}, ${pf});`,
46
+ `vec3 ${cv} = vec3(${fv});`,
47
+ ].join('\n ');
48
+ }
49
+ }
50
+ WaveTexture.instanceSpecificDef = false;
51
+ WaveTexture.glslFunction = `
52
+ float _st_waveHash(vec3 p) {
53
+ return fract(sin(dot(p, vec3(127.1, 311.7, 74.7))) * 43758.5453);
54
+ }
55
+ float _st_waveNoise(vec3 p) {
56
+ vec3 pi = floor(p), pf = p - pi, u = pf * pf * (3.0 - 2.0 * pf);
57
+ return mix(mix(mix(_st_waveHash(pi), _st_waveHash(pi+vec3(1,0,0)), u.x),
58
+ mix(_st_waveHash(pi+vec3(0,1,0)), _st_waveHash(pi+vec3(1,1,0)), u.x), u.y),
59
+ mix(mix(_st_waveHash(pi+vec3(0,0,1)), _st_waveHash(pi+vec3(1,0,1)), u.x),
60
+ mix(_st_waveHash(pi+vec3(0,1,1)), _st_waveHash(pi+vec3(1,1,1)), u.x), u.y), u.z);
61
+ }
62
+ float _st_waveTexture(vec3 p, float scale, float distortion, float detail, float dScale, float dRough, int waveType, int profile) {
63
+ p *= scale;
64
+ float dist = (waveType == 0) ? p.x + p.y + p.z : length(p);
65
+ float n = 0.0, amp = 1.0, freq = 1.0, maxAmp = 0.0;
66
+ int oct = int(clamp(detail, 0.0, 8.0));
67
+ for (int i = 0; i < 8; i++) {
68
+ if (i >= oct) break;
69
+ n += amp * _st_waveNoise(p * freq * dScale);
70
+ maxAmp += amp; amp *= dRough; freq *= 2.0;
71
+ }
72
+ dist += distortion * (maxAmp > 0.0 ? n / maxAmp : 0.0);
73
+ float wave = 0.5 + 0.5 * sin(dist * 6.28318);
74
+ if (profile == 1) wave = fract(dist / 6.28318);
75
+ if (profile == 2) wave = abs(2.0 * fract(dist / 6.28318) - 1.0);
76
+ return wave;
77
+ }`;
@@ -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 WavelengthInputs {
6
+ wavelength?: OutputSocket | number;
7
+ }
8
+ /**
9
+ * Wavelength — Blender "Wavelength" node equivalent.
10
+ * Converts a visible light wavelength (380–780 nm) into an RGB colour.
11
+ *
12
+ * Inputs: wavelength (float, nanometres — 380 to 780)
13
+ * Outputs: Color (color)
14
+ */
15
+ export declare class Wavelength 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?: WavelengthInputs);
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=Wavelength.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Wavelength.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/Wavelength.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,gBAAgB;IAC/B,UAAU,CAAC,EAAE,YAAY,GAAG,MAAM,CAAA;CACnC;AAED;;;;;;GAMG;AACH,qBAAa,UAAW,SAAQ,WAAW;IACzC,IAAI,QAAQ,WAA0B;IACtC,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAanB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,gBAAqB;IAQzC,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAIzC"}
@@ -0,0 +1,43 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * Wavelength — Blender "Wavelength" node equivalent.
4
+ * Converts a visible light wavelength (380–780 nm) into an RGB colour.
5
+ *
6
+ * Inputs: wavelength (float, nanometres — 380 to 780)
7
+ * Outputs: Color (color)
8
+ */
9
+ export class Wavelength extends ProcessNode {
10
+ get nodeType() { return 'Wavelength'; }
11
+ get metadata() {
12
+ return { label: 'Wavelength', category: 'Color', color: '#633060', cost: 'low' };
13
+ }
14
+ constructor(inputs = {}) {
15
+ super('Wavelength');
16
+ this._inputs = this.createInputs(inputs, {
17
+ wavelength: ['float', inputs.wavelength ?? 550.0],
18
+ });
19
+ this._outputs = this.createOutputs({ Color: 'color' });
20
+ }
21
+ getInputSockets() { return this._inputs; }
22
+ getOutputSockets() { return this._outputs; }
23
+ compileDefs() { return Wavelength.glslFunction; }
24
+ compileCall(ctx) {
25
+ const w = ctx.resolveInput(this._inputs.wavelength);
26
+ return `vec3 ${ctx.outputVar(this, 'Color')} = _st_wavelength(${w});`;
27
+ }
28
+ }
29
+ Wavelength.instanceSpecificDef = false;
30
+ Wavelength.glslFunction = `
31
+ vec3 _st_wavelength(float w) {
32
+ w = clamp(w, 380.0, 780.0);
33
+ float r = 0.0, g = 0.0, b = 0.0;
34
+ if (w < 440.0) { r = (440.0 - w) / 60.0; b = 1.0; }
35
+ else if (w < 490.0) { g = (w - 440.0) / 50.0; b = 1.0; }
36
+ else if (w < 510.0) { g = 1.0; b = (510.0 - w) / 20.0; }
37
+ else if (w < 580.0) { r = (w - 510.0) / 70.0; g = 1.0; }
38
+ else if (w < 645.0) { r = 1.0; g = (645.0 - w) / 65.0; }
39
+ else { r = 1.0; }
40
+ float factor = (w < 420.0) ? 0.3 + 0.7 * (w - 380.0) / 40.0
41
+ : (w > 700.0) ? 0.3 + 0.7 * (780.0 - w) / 80.0 : 1.0;
42
+ return pow(vec3(r, g, b) * factor, vec3(0.8));
43
+ }`;
@@ -0,0 +1,27 @@
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 WhiteNoiseInputs {
6
+ vector?: OutputSocket;
7
+ }
8
+ /**
9
+ * White Noise — Blender "White Noise" texture node equivalent.
10
+ * Pure pixel-perfect random values — no spatial correlation.
11
+ *
12
+ * Outputs: Value (float), Color (color)
13
+ */
14
+ export declare class WhiteNoise extends ProcessNode {
15
+ get nodeType(): string;
16
+ static instanceSpecificDef: boolean;
17
+ get metadata(): NodeMetadata;
18
+ static glslFunction: string;
19
+ private readonly _inputs;
20
+ private readonly _outputs;
21
+ constructor(inputs?: WhiteNoiseInputs);
22
+ getInputSockets(): Record<string, import("../../core/InputSocket.js").InputSocket<unknown>>;
23
+ getOutputSockets(): Record<string, OutputSocket>;
24
+ compileDefs(): string;
25
+ compileCall(ctx: CompileContext): string;
26
+ }
27
+ //# sourceMappingURL=WhiteNoise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WhiteNoise.d.ts","sourceRoot":"","sources":["../../../src/nodes/process/WhiteNoise.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,gBAAgB;IAC/B,MAAM,CAAC,EAAE,YAAY,CAAA;CACtB;AAED;;;;;GAKG;AACH,qBAAa,UAAW,SAAQ,WAAW;IACzC,IAAI,QAAQ,WAA0B;IACtC,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAED,MAAM,CAAC,YAAY,SAUnB;IAEA,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2E;IACnG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmE;gBAEhF,MAAM,GAAE,gBAAqB;IAMzC,eAAe;IACf,gBAAgB;IAChB,WAAW;IAEX,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAWzC"}
@@ -0,0 +1,44 @@
1
+ import { ProcessNode } from '../../core/ProcessNode.js';
2
+ /**
3
+ * White Noise — Blender "White Noise" texture node equivalent.
4
+ * Pure pixel-perfect random values — no spatial correlation.
5
+ *
6
+ * Outputs: Value (float), Color (color)
7
+ */
8
+ export class WhiteNoise extends ProcessNode {
9
+ get nodeType() { return 'WhiteNoise'; }
10
+ get metadata() {
11
+ return { label: 'White Noise', category: 'Texture', color: '#3a6b3a', cost: 'low' };
12
+ }
13
+ constructor(inputs = {}) {
14
+ super('WhiteNoise');
15
+ this._inputs = this.createInputs(inputs, { vector: ['color', null] });
16
+ this._outputs = this.createOutputs({ Value: 'float', Color: 'color' });
17
+ }
18
+ getInputSockets() { return this._inputs; }
19
+ getOutputSockets() { return this._outputs; }
20
+ compileDefs() { return WhiteNoise.glslFunction; }
21
+ compileCall(ctx) {
22
+ const vec = this._inputs.vector.isConnected()
23
+ ? `vec3(${ctx.outputVar(this._inputs.vector.connection.node, this._inputs.vector.connection.name)})`
24
+ : 'vec3(vUv, 0.0)';
25
+ const fv = ctx.outputVar(this, 'Value');
26
+ const cv = ctx.outputVar(this, 'Color');
27
+ return [
28
+ `float ${fv} = _st_whiteNoise1(${vec});`,
29
+ `vec3 ${cv} = _st_whiteNoise3(${vec});`,
30
+ ].join('\n ');
31
+ }
32
+ }
33
+ WhiteNoise.instanceSpecificDef = false;
34
+ WhiteNoise.glslFunction = `
35
+ float _st_whiteNoise1(vec3 p) {
36
+ return fract(sin(dot(p, vec3(127.1, 311.7, 74.7))) * 43758.5453);
37
+ }
38
+ vec3 _st_whiteNoise3(vec3 p) {
39
+ return vec3(
40
+ fract(sin(dot(p, vec3(127.1, 311.7, 74.7))) * 43758.5453),
41
+ fract(sin(dot(p, vec3(269.5, 183.3, 246.1))) * 43758.5453),
42
+ fract(sin(dot(p, vec3(113.5, 271.9, 124.6))) * 43758.5453)
43
+ );
44
+ }`;
@@ -0,0 +1,47 @@
1
+ import { InputNode } from '../../core/InputNode.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
+ import type { InputSocket } from '../../core/InputSocket.js';
6
+ export interface AmbientOcclusionInputs {
7
+ color?: OutputSocket | [number, number, number] | string;
8
+ }
9
+ /**
10
+ * Ambient Occlusion — Blender "Ambient Occlusion" input node equivalent.
11
+ *
12
+ * Approximates SSAO using a fixed hemisphere sample kernel evaluated against
13
+ * neighboring surface normals. Because no depth buffer is available in a
14
+ * forward-rendered fragment shader, the implementation samples offset
15
+ * positions in view space and estimates occlusion from the surface normal
16
+ * divergence between the central fragment and each sample.
17
+ *
18
+ * Parameters:
19
+ * samples (number) — hemisphere sample count [1–16], default 8
20
+ * distance (number) — sampling radius in world units, default 0.5
21
+ * inside (number) — 0 = exterior AO (default), 1 = invert for interior surfaces
22
+ *
23
+ * Inputs:
24
+ * Color (color) — base color to attenuate by the AO factor
25
+ *
26
+ * Outputs:
27
+ * Color (color) — input color darkened by AO
28
+ * AO (float) — raw ambient occlusion factor [0–1]
29
+ */
30
+ export declare class AmbientOcclusion extends InputNode {
31
+ get nodeType(): string;
32
+ static instanceSpecificDef: boolean;
33
+ get metadata(): NodeMetadata;
34
+ parameters: {
35
+ samples: number;
36
+ distance: number;
37
+ inside: number;
38
+ };
39
+ private readonly _inputs;
40
+ private readonly _outputs;
41
+ constructor(inputs?: AmbientOcclusionInputs);
42
+ getInputSockets(): Record<string, InputSocket<unknown>>;
43
+ getOutputSockets(): Record<string, OutputSocket>;
44
+ compileDefs(): string;
45
+ compileCall(ctx: CompileContext): string;
46
+ }
47
+ //# sourceMappingURL=AmbientOcclusion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AmbientOcclusion.d.ts","sourceRoot":"","sources":["../../../src/nodes/shader/AmbientOcclusion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAG,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAA;CAC1D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,gBAAiB,SAAQ,SAAS;IAC7C,IAAI,QAAQ,WAAgC;IAC5C,MAAM,CAAC,mBAAmB,UAAQ;IAElC,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAEQ,UAAU,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAIzE;IAED,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;gBAE3C,MAAM,GAAE,sBAA2B;IAQ/C,eAAe;IACf,gBAAgB;IAEhB,WAAW,IAAI,MAAM;IAsErB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;CAkBzC"}
@@ -0,0 +1,128 @@
1
+ import { InputNode } from '../../core/InputNode.js';
2
+ /**
3
+ * Ambient Occlusion — Blender "Ambient Occlusion" input node equivalent.
4
+ *
5
+ * Approximates SSAO using a fixed hemisphere sample kernel evaluated against
6
+ * neighboring surface normals. Because no depth buffer is available in a
7
+ * forward-rendered fragment shader, the implementation samples offset
8
+ * positions in view space and estimates occlusion from the surface normal
9
+ * divergence between the central fragment and each sample.
10
+ *
11
+ * Parameters:
12
+ * samples (number) — hemisphere sample count [1–16], default 8
13
+ * distance (number) — sampling radius in world units, default 0.5
14
+ * inside (number) — 0 = exterior AO (default), 1 = invert for interior surfaces
15
+ *
16
+ * Inputs:
17
+ * Color (color) — base color to attenuate by the AO factor
18
+ *
19
+ * Outputs:
20
+ * Color (color) — input color darkened by AO
21
+ * AO (float) — raw ambient occlusion factor [0–1]
22
+ */
23
+ export class AmbientOcclusion extends InputNode {
24
+ get nodeType() { return 'AmbientOcclusion'; }
25
+ get metadata() {
26
+ return { label: 'Ambient Occlusion', category: 'Input', color: '#3d6b96', cost: 'high', costNote: 'multi-sample hemisphere loop' };
27
+ }
28
+ constructor(inputs = {}) {
29
+ super('AmbientOcclusion');
30
+ this.parameters = {
31
+ samples: 8,
32
+ distance: 0.5,
33
+ inside: 0,
34
+ };
35
+ this._inputs = this.createInputs(inputs, {
36
+ color: ['color', inputs.color ?? '#ffffff'],
37
+ });
38
+ this._outputs = this.createOutputs({ Color: 'color', AO: 'float' });
39
+ }
40
+ getInputSockets() { return this._inputs; }
41
+ getOutputSockets() { return this._outputs; }
42
+ compileDefs() {
43
+ // Fixed-size hemisphere kernel (16 directions) — cap prevents unbounded loops.
44
+ // Hash-based pseudo-random rotation avoids a texture lookup.
45
+ // SECURITY: loop is bounded by compile-time constant 16.
46
+ return `
47
+ float _st_ao_hash(vec2 p) {
48
+ p = fract(p * vec2(234.34, 435.345));
49
+ p += dot(p, p + 34.23);
50
+ return fract(p.x * p.y);
51
+ }
52
+
53
+ float _st_ambientOcclusion(vec3 pos, vec3 N, float dist, int samples, bool inside) {
54
+ // 16-element hemisphere kernel (fixed compile-time size)
55
+ vec3 kernel[16];
56
+ kernel[0] = vec3( 0.5381, 0.1856, -0.4319);
57
+ kernel[1] = vec3( 0.1379, 0.2486, 0.4430);
58
+ kernel[2] = vec3( 0.3371, 0.5679, -0.0057);
59
+ kernel[3] = vec3(-0.6999, -0.0451, -0.0019);
60
+ kernel[4] = vec3( 0.0689, -0.1598, -0.8547);
61
+ kernel[5] = vec3( 0.0560, 0.0069, -0.1843);
62
+ kernel[6] = vec3(-0.0146, 0.1402, 0.0762);
63
+ kernel[7] = vec3( 0.0100, -0.1924, -0.0344);
64
+ kernel[8] = vec3(-0.3577, -0.5301, -0.4358);
65
+ kernel[9] = vec3(-0.3169, 0.1063, 0.0158);
66
+ kernel[10] = vec3( 0.0103, -0.5869, 0.0046);
67
+ kernel[11] = vec3(-0.0897, -0.4940, 0.3287);
68
+ kernel[12] = vec3( 0.7119, -0.0154, -0.0918);
69
+ kernel[13] = vec3(-0.0533, 0.0596, -0.5411);
70
+ kernel[14] = vec3( 0.0352, -0.0631, 0.5460);
71
+ kernel[15] = vec3(-0.4776, 0.2847, -0.0271);
72
+
73
+ float occlusion = 0.0;
74
+ float noise = _st_ao_hash(pos.xy + pos.z);
75
+ float c = cos(noise * 6.2832);
76
+ float s = sin(noise * 6.2832);
77
+
78
+ // Build tangent frame from normal
79
+ vec3 up = abs(N.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
80
+ vec3 tangent = normalize(cross(up, N));
81
+ vec3 bitan = cross(N, tangent);
82
+ mat3 tbn = mat3(tangent, bitan, N);
83
+
84
+ int clampedSamples = clamp(samples, 1, 16);
85
+ for (int i = 0; i < 16; i++) {
86
+ if (i >= clampedSamples) break;
87
+
88
+ // Rotate sample by noise to reduce banding
89
+ vec3 ks = kernel[i];
90
+ vec3 rotated = vec3(
91
+ c * ks.x - s * ks.y,
92
+ s * ks.x + c * ks.y,
93
+ ks.z
94
+ );
95
+ // Flip to hemisphere
96
+ if (dot(rotated, N) < 0.0) rotated = -rotated;
97
+ vec3 samplePos = pos + tbn * rotated * dist;
98
+
99
+ // Estimate occlusion: if sample is "behind" the surface normal, it is occluded
100
+ vec3 dir = samplePos - pos;
101
+ float contrib = max(dot(normalize(dir), N), 0.0);
102
+ float decay = 1.0 - clamp(length(dir) / dist, 0.0, 1.0);
103
+ occlusion += contrib * decay;
104
+ }
105
+
106
+ occlusion = 1.0 - (occlusion / float(clampedSamples));
107
+ return inside ? 1.0 - occlusion : occlusion;
108
+ }
109
+ `;
110
+ }
111
+ compileCall(ctx) {
112
+ const colorIn = ctx.resolveInput(this._inputs.color);
113
+ const outColor = ctx.outputVar(this, 'Color');
114
+ const outAO = ctx.outputVar(this, 'AO');
115
+ // SECURITY: validate samples is a finite positive integer before GLSL
116
+ const rawSamples = this.parameters.samples;
117
+ const safeSamples = (Number.isFinite(rawSamples) && rawSamples >= 1)
118
+ ? Math.min(Math.floor(rawSamples), 16)
119
+ : 8;
120
+ const inside = this.parameters.inside !== 0 ? 'true' : 'false';
121
+ const dist = Number.isFinite(this.parameters.distance) ? this.parameters.distance.toFixed(4) : '0.5000';
122
+ return [
123
+ `float ${outAO} = _st_ambientOcclusion(vPosition, normalize(vNormal), ${dist}, ${safeSamples}, ${inside});`,
124
+ `vec3 ${outColor} = ${colorIn} * ${outAO};`,
125
+ ].join('\n ');
126
+ }
127
+ }
128
+ AmbientOcclusion.instanceSpecificDef = false;