@nice2dev/game-engine 1.3.15 → 1.3.16

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 (434) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cjs/accessibility/Accessibility.js +152 -165
  3. package/dist/cjs/ai/AI.js +292 -294
  4. package/dist/cjs/ai/BehaviorTree.js +1029 -1113
  5. package/dist/cjs/ai/StateMachine.js +694 -756
  6. package/dist/cjs/animation/Animation.js +232 -241
  7. package/dist/cjs/audio/AudioAdvanced.js +221 -236
  8. package/dist/cjs/audio/AudioBridge.js +441 -435
  9. package/dist/cjs/audio/AudioManager.js +242 -259
  10. package/dist/cjs/build-cloud/BuildOrchestration.js +1059 -1098
  11. package/dist/cjs/build-cloud/GodotBuildCloud.js +641 -670
  12. package/dist/cjs/build-cloud/UnityBuildCloud.js +563 -610
  13. package/dist/cjs/build-cloud/UnrealBuildCloud.js +610 -635
  14. package/dist/cjs/core/EventBus.js +51 -56
  15. package/dist/cjs/core/GameClock.js +62 -66
  16. package/dist/cjs/core/GameConfig.js +72 -79
  17. package/dist/cjs/core/GameLoop.js +80 -89
  18. package/dist/cjs/core/ServiceLocator.js +61 -65
  19. package/dist/cjs/core/Validation.js +72 -82
  20. package/dist/cjs/core/math.js +108 -112
  21. package/dist/cjs/devtools/DevTools.js +542 -563
  22. package/dist/cjs/devtools/DeveloperExperience.js +521 -559
  23. package/dist/cjs/devtools/GameplayAnalytics.js +636 -646
  24. package/dist/cjs/dialogue/DialogueSystem.js +984 -986
  25. package/dist/cjs/docs/DocGenerator.js +339 -364
  26. package/dist/cjs/ecs/World.js +355 -371
  27. package/dist/cjs/editor/AchievementEditor.js +580 -636
  28. package/dist/cjs/editor/AdvancedEditor.js +184 -191
  29. package/dist/cjs/editor/AnimationRetargeting.js +696 -741
  30. package/dist/cjs/editor/AssetBrowser.js +1072 -1160
  31. package/dist/cjs/editor/AssetManager.js +187 -192
  32. package/dist/cjs/editor/ConsolePro.js +971 -1061
  33. package/dist/cjs/editor/CraftingEditor.js +680 -730
  34. package/dist/cjs/editor/DebugTools.js +187 -185
  35. package/dist/cjs/editor/DialogueSystem.js +844 -901
  36. package/dist/cjs/editor/LeaderboardSystem.js +429 -483
  37. package/dist/cjs/editor/NiceGameEditor.js +1903 -1201
  38. package/dist/cjs/editor/PrefabSystem.js +772 -838
  39. package/dist/cjs/editor/ProfilerPanel.js +649 -700
  40. package/dist/cjs/editor/QuestEditor.js +792 -839
  41. package/dist/cjs/editor/ReplaySystem.js +585 -634
  42. package/dist/cjs/editor/SceneEditor.js +176 -200
  43. package/dist/cjs/editor/ScreenshotMode.js +621 -688
  44. package/dist/cjs/editor/ShaderGraph.js +1556 -1582
  45. package/dist/cjs/editor/TimelineEditor.js +715 -778
  46. package/dist/cjs/editor/UndoRedoPro.js +830 -904
  47. package/dist/cjs/editor/VRARMode.js +582 -645
  48. package/dist/cjs/engine/NiceGameEngine.js +141 -164
  49. package/dist/cjs/engine/SaveSystem.js +441 -495
  50. package/dist/cjs/enterprise/Enterprise.js +254 -261
  51. package/dist/cjs/export/BevyExporter.js +927 -967
  52. package/dist/cjs/export/CocosExporter.js +644 -673
  53. package/dist/cjs/export/Construct3Exporter.js +783 -794
  54. package/dist/cjs/export/DefoldExporter.js +1028 -1069
  55. package/dist/cjs/export/GDevelopExporter.js +674 -708
  56. package/dist/cjs/export/GameMakerExporter.js +791 -805
  57. package/dist/cjs/export/GodotExporter.js +1003 -1045
  58. package/dist/cjs/export/MinecraftBedrockExporter.js +573 -578
  59. package/dist/cjs/export/MonoGameExporter.js +1265 -1293
  60. package/dist/cjs/export/Pico8Exporter.js +766 -812
  61. package/dist/cjs/export/PlatformExporter.js +188 -206
  62. package/dist/cjs/export/RPGMakerExporter.js +860 -879
  63. package/dist/cjs/export/RobloxExporter.js +883 -919
  64. package/dist/cjs/export/Solar2DExporter.js +1218 -1256
  65. package/dist/cjs/export/ThreeJSExporter.js +1006 -1073
  66. package/dist/cjs/export/Tic80Exporter.js +1210 -1267
  67. package/dist/cjs/export/UnityExporter.js +1116 -1131
  68. package/dist/cjs/export/UnrealExporter.js +889 -919
  69. package/dist/cjs/export/WebExporter.js +931 -970
  70. package/dist/cjs/export/index.js +42 -65
  71. package/dist/cjs/godot-integration/GodotAssetLibrary.js +659 -692
  72. package/dist/cjs/godot-integration/GodotImport.js +929 -1027
  73. package/dist/cjs/godot-integration/GodotLiveLink.js +915 -945
  74. package/dist/cjs/godot-integration/components/GodotProjectBrowser.js +911 -611
  75. package/dist/cjs/i18n/I18n.js +860 -900
  76. package/dist/cjs/i18n/useTranslation.js +84 -89
  77. package/dist/cjs/import/AsepriteImporter.js +658 -716
  78. package/dist/cjs/import/DragonBonesImporter.js +437 -461
  79. package/dist/cjs/import/GameMakerImporter.js +511 -521
  80. package/dist/cjs/import/GodotSceneImporter.js +788 -822
  81. package/dist/cjs/import/LDtkImporter.js +436 -454
  82. package/dist/cjs/import/Live2DImporter.js +497 -518
  83. package/dist/cjs/import/NdgFormat.js +424 -457
  84. package/dist/cjs/import/OgmoImporter.js +466 -493
  85. package/dist/cjs/import/RPGMakerImporter.js +451 -477
  86. package/dist/cjs/import/SceneImporter.js +378 -423
  87. package/dist/cjs/import/SpineImporter.js +511 -546
  88. package/dist/cjs/import/SpriterImporter.js +590 -613
  89. package/dist/cjs/import/TiledMapImporter.js +811 -846
  90. package/dist/cjs/import/UnitySceneImporter.js +687 -703
  91. package/dist/cjs/import/index.js +206 -251
  92. package/dist/cjs/index.js +275 -278
  93. package/dist/cjs/input/GamepadNavigation.js +185 -205
  94. package/dist/cjs/input/InputManager.js +397 -421
  95. package/dist/cjs/input/useGamepads.js +70 -81
  96. package/dist/cjs/integration/IconSprite.js +129 -256
  97. package/dist/cjs/inventory/InventorySystem.js +920 -995
  98. package/dist/cjs/kids/KidMode.js +997 -1022
  99. package/dist/cjs/kids/KidTools.js +570 -594
  100. package/dist/cjs/monetization/Monetization.js +170 -177
  101. package/dist/cjs/multiplayer/LocalMultiplayer.js +287 -287
  102. package/dist/cjs/multiplayer/MiniGameTypes.js +49 -59
  103. package/dist/cjs/native-engine/AnimationSystem.js +731 -806
  104. package/dist/cjs/native-engine/AssetPipeline.js +454 -515
  105. package/dist/cjs/native-engine/AudioEngine.js +763 -804
  106. package/dist/cjs/native-engine/InputSystem.js +1075 -1145
  107. package/dist/cjs/native-engine/NetworkingSystem.js +733 -793
  108. package/dist/cjs/native-engine/PhysicsEngine.js +583 -607
  109. package/dist/cjs/native-engine/RenderingEngine.js +302 -350
  110. package/dist/cjs/native-engine/SceneGraph.js +769 -808
  111. package/dist/cjs/network/MultiplayerTransport.js +97 -132
  112. package/dist/cjs/network/Networking.js +549 -564
  113. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/AbortController.js +21 -29
  114. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/AccessTokenHttpClient.js +40 -48
  115. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/DefaultHttpClient.js +35 -43
  116. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/DefaultReconnectPolicy.js +10 -15
  117. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Errors.js +103 -135
  118. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/FetchHttpClient.js +131 -158
  119. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HandshakeProtocol.js +39 -53
  120. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HeaderNames.js +5 -8
  121. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HttpClient.js +40 -48
  122. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HttpConnection.js +494 -572
  123. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HubConnection.js +826 -953
  124. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HubConnectionBuilder.js +125 -146
  125. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/IHubProtocol.js +13 -23
  126. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ILogger.js +11 -25
  127. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ITransport.js +13 -24
  128. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/JsonHubProtocol.js +108 -121
  129. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Loggers.js +10 -14
  130. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/LongPollingTransport.js +150 -185
  131. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/MessageBuffer.js +158 -196
  132. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ServerSentEventsTransport.js +90 -105
  133. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Subject.js +30 -35
  134. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/TextMessageFormat.js +16 -21
  135. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Utils.js +215 -248
  136. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/WebSocketTransport.js +135 -157
  137. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/XhrHttpClient.js +76 -85
  138. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/index.js +24 -27
  139. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/pkg-version.js +3 -4
  140. package/dist/cjs/pathfinding/Pathfinding.js +245 -263
  141. package/dist/cjs/performance/AssetStreaming.js +561 -635
  142. package/dist/cjs/performance/BenchmarkSuite.js +283 -311
  143. package/dist/cjs/performance/DeltaCompression.js +467 -526
  144. package/dist/cjs/performance/DeterministicPhysics.js +450 -498
  145. package/dist/cjs/performance/ECSOptimization.js +644 -695
  146. package/dist/cjs/performance/GameSaveSystem.js +509 -556
  147. package/dist/cjs/performance/HotReload.js +447 -500
  148. package/dist/cjs/performance/InputRecording.js +511 -561
  149. package/dist/cjs/performance/InterestManagement.js +453 -500
  150. package/dist/cjs/performance/LocalizationRuntime.js +376 -423
  151. package/dist/cjs/performance/MemoryManagement.js +410 -470
  152. package/dist/cjs/performance/ModSupport.js +445 -496
  153. package/dist/cjs/performance/MultiThreadedPhysics.js +400 -443
  154. package/dist/cjs/performance/NetworkPrediction.js +424 -482
  155. package/dist/cjs/performance/ObjectPooling.js +569 -617
  156. package/dist/cjs/performance/Performance.js +174 -190
  157. package/dist/cjs/performance/PerformanceAdvanced.js +614 -637
  158. package/dist/cjs/performance/WebGPURenderer.js +656 -683
  159. package/dist/cjs/physics/PhysicsAdvanced.js +345 -379
  160. package/dist/cjs/physics/PhysicsEngine2D.js +391 -427
  161. package/dist/cjs/plugins/PluginSDK.js +432 -466
  162. package/dist/cjs/plugins/PluginTestKit.js +307 -330
  163. package/dist/cjs/procedural/Procedural.js +243 -254
  164. package/dist/cjs/procedural/WorldBuilding.js +297 -314
  165. package/dist/cjs/quest/QuestSystem.js +975 -932
  166. package/dist/cjs/release/MobileExport.js +157 -163
  167. package/dist/cjs/release/Release.js +225 -238
  168. package/dist/cjs/rendering/Camera2D.js +121 -124
  169. package/dist/cjs/rendering/Renderer2D.js +321 -335
  170. package/dist/cjs/rendering/WebGPURenderPipeline.js +632 -651
  171. package/dist/cjs/runtime3d/Runtime3D.js +359 -378
  172. package/dist/cjs/runtime3d/SceneEditor3D.js +252 -263
  173. package/dist/cjs/scene/SceneManager.js +177 -193
  174. package/dist/cjs/scripting/GraphToAST.js +574 -547
  175. package/dist/cjs/scripting/LanguageExporter.js +254 -279
  176. package/dist/cjs/scripting/NodeGraph.js +546 -570
  177. package/dist/cjs/scripting/ScriptAST.js +31 -39
  178. package/dist/cjs/scripting/VisualScripting2.js +1016 -1065
  179. package/dist/cjs/scripting/exporters/CSharpExporter.js +464 -496
  180. package/dist/cjs/scripting/exporters/GDScriptExporter.js +390 -442
  181. package/dist/cjs/scripting/exporters/LuaExporter.js +406 -447
  182. package/dist/cjs/scripting/exporters/PythonExporter.js +484 -549
  183. package/dist/cjs/scripting/exporters/RustExporter.js +459 -512
  184. package/dist/cjs/scripting/exporters/TypeScriptExporter.js +505 -556
  185. package/dist/cjs/social/Social.js +72 -80
  186. package/dist/cjs/systems/LightingSystem.js +844 -931
  187. package/dist/cjs/systems/ParticleSystem2.js +1447 -1451
  188. package/dist/cjs/systems/PhysicsDebugSystem.js +1070 -1141
  189. package/dist/cjs/systems/TerrainSystem.js +985 -1098
  190. package/dist/cjs/templates/ActionTemplates.js +296 -309
  191. package/dist/cjs/templates/FightingTemplate.js +417 -463
  192. package/dist/cjs/templates/MetroidvaniaTemplate.js +353 -405
  193. package/dist/cjs/templates/PartyTemplates.js +190 -202
  194. package/dist/cjs/templates/PuzzleTemplates.js +245 -261
  195. package/dist/cjs/templates/RPGTemplates.js +160 -178
  196. package/dist/cjs/templates/SportsTemplates.js +237 -250
  197. package/dist/cjs/templates/StrategyTemplates.js +143 -153
  198. package/dist/cjs/templates/SurvivalTemplate.js +336 -380
  199. package/dist/cjs/templates/WaveDefense.js +499 -526
  200. package/dist/cjs/tilemap/Tilemap.js +207 -214
  201. package/dist/cjs/tutorials/TutorialBranching.js +396 -417
  202. package/dist/cjs/tutorials/TutorialEngine.js +888 -931
  203. package/dist/cjs/tutorials/TutorialOverlay.js +602 -640
  204. package/dist/cjs/tutorials/content/Tutorials_T05_T08.js +787 -809
  205. package/dist/cjs/tutorials/content/Tutorials_T09_T11.js +736 -756
  206. package/dist/cjs/tutorials/content/Tutorials_T12_T15.js +754 -778
  207. package/dist/cjs/ui/GameUI.js +295 -312
  208. package/dist/cjs/unity-integration/UnityAssetStore.js +700 -741
  209. package/dist/cjs/unity-integration/UnityImport.js +1066 -1176
  210. package/dist/cjs/unity-integration/UnityLiveLink.js +934 -981
  211. package/dist/cjs/unity-integration/components/UnityAssetStoreBrowser.js +1233 -757
  212. package/dist/cjs/unity-integration/components/UnityProjectBrowser.js +1240 -768
  213. package/dist/cjs/unreal-integration/UnrealImport.js +391 -412
  214. package/dist/cjs/unreal-integration/UnrealLiveLink.js +1102 -1137
  215. package/dist/cjs/unreal-integration/UnrealMarketplace.js +436 -473
  216. package/dist/cjs/unreal-integration/components/UnrealProjectBrowser.js +1150 -767
  217. package/dist/cjs/xr/ARVR.js +167 -175
  218. package/dist/esm/accessibility/Accessibility.js +160 -164
  219. package/dist/esm/ai/AI.js +310 -293
  220. package/dist/esm/ai/BehaviorTree.js +1057 -1112
  221. package/dist/esm/ai/StateMachine.js +709 -755
  222. package/dist/esm/animation/Animation.js +237 -240
  223. package/dist/esm/audio/AudioAdvanced.js +239 -235
  224. package/dist/esm/audio/AudioBridge.js +448 -434
  225. package/dist/esm/audio/AudioManager.js +243 -258
  226. package/dist/esm/build-cloud/BuildOrchestration.js +1071 -1097
  227. package/dist/esm/build-cloud/GodotBuildCloud.js +647 -669
  228. package/dist/esm/build-cloud/UnityBuildCloud.js +571 -609
  229. package/dist/esm/build-cloud/UnrealBuildCloud.js +615 -634
  230. package/dist/esm/core/EventBus.js +52 -55
  231. package/dist/esm/core/GameClock.js +63 -65
  232. package/dist/esm/core/GameConfig.js +77 -78
  233. package/dist/esm/core/GameLoop.js +81 -88
  234. package/dist/esm/core/ServiceLocator.js +63 -64
  235. package/dist/esm/core/Validation.js +82 -81
  236. package/dist/esm/core/math.js +109 -111
  237. package/dist/esm/devtools/DevTools.js +546 -562
  238. package/dist/esm/devtools/DeveloperExperience.js +535 -558
  239. package/dist/esm/devtools/GameplayAnalytics.js +647 -645
  240. package/dist/esm/dialogue/DialogueSystem.js +998 -985
  241. package/dist/esm/docs/DocGenerator.js +342 -363
  242. package/dist/esm/ecs/World.js +358 -370
  243. package/dist/esm/editor/AchievementEditor.js +584 -635
  244. package/dist/esm/editor/AdvancedEditor.js +191 -190
  245. package/dist/esm/editor/AnimationRetargeting.js +700 -740
  246. package/dist/esm/editor/AssetBrowser.js +1078 -1159
  247. package/dist/esm/editor/AssetManager.js +188 -191
  248. package/dist/esm/editor/ConsolePro.js +977 -1060
  249. package/dist/esm/editor/CraftingEditor.js +684 -729
  250. package/dist/esm/editor/DebugTools.js +194 -184
  251. package/dist/esm/editor/DialogueSystem.js +849 -900
  252. package/dist/esm/editor/LeaderboardSystem.js +433 -482
  253. package/dist/esm/editor/NiceGameEditor.js +1908 -1200
  254. package/dist/esm/editor/PrefabSystem.js +777 -837
  255. package/dist/esm/editor/ProfilerPanel.js +654 -699
  256. package/dist/esm/editor/QuestEditor.js +795 -838
  257. package/dist/esm/editor/ReplaySystem.js +591 -633
  258. package/dist/esm/editor/SceneEditor.js +189 -199
  259. package/dist/esm/editor/ScreenshotMode.js +628 -687
  260. package/dist/esm/editor/ShaderGraph.js +1565 -1581
  261. package/dist/esm/editor/TimelineEditor.js +733 -777
  262. package/dist/esm/editor/UndoRedoPro.js +835 -903
  263. package/dist/esm/editor/VRARMode.js +586 -644
  264. package/dist/esm/engine/NiceGameEngine.js +142 -163
  265. package/dist/esm/engine/SaveSystem.js +447 -494
  266. package/dist/esm/enterprise/Enterprise.js +265 -260
  267. package/dist/esm/export/BevyExporter.js +929 -966
  268. package/dist/esm/export/CocosExporter.js +646 -672
  269. package/dist/esm/export/Construct3Exporter.js +785 -793
  270. package/dist/esm/export/DefoldExporter.js +1030 -1068
  271. package/dist/esm/export/GDevelopExporter.js +676 -707
  272. package/dist/esm/export/GameMakerExporter.js +793 -804
  273. package/dist/esm/export/GodotExporter.js +1004 -1044
  274. package/dist/esm/export/MinecraftBedrockExporter.js +575 -577
  275. package/dist/esm/export/MonoGameExporter.js +1267 -1292
  276. package/dist/esm/export/Pico8Exporter.js +768 -811
  277. package/dist/esm/export/PlatformExporter.js +193 -205
  278. package/dist/esm/export/RPGMakerExporter.js +862 -878
  279. package/dist/esm/export/RobloxExporter.js +885 -918
  280. package/dist/esm/export/Solar2DExporter.js +1220 -1255
  281. package/dist/esm/export/ThreeJSExporter.js +1007 -1072
  282. package/dist/esm/export/Tic80Exporter.js +1212 -1266
  283. package/dist/esm/export/UnityExporter.js +1117 -1130
  284. package/dist/esm/export/UnrealExporter.js +891 -918
  285. package/dist/esm/export/WebExporter.js +933 -969
  286. package/dist/esm/export/index.js +86 -71
  287. package/dist/esm/godot-integration/GodotAssetLibrary.js +663 -691
  288. package/dist/esm/godot-integration/GodotImport.js +935 -1026
  289. package/dist/esm/godot-integration/GodotLiveLink.js +918 -944
  290. package/dist/esm/godot-integration/components/GodotProjectBrowser.js +912 -610
  291. package/dist/esm/i18n/I18n.js +871 -899
  292. package/dist/esm/i18n/useTranslation.js +88 -88
  293. package/dist/esm/import/AsepriteImporter.js +637 -715
  294. package/dist/esm/import/DragonBonesImporter.js +417 -460
  295. package/dist/esm/import/GameMakerImporter.js +491 -520
  296. package/dist/esm/import/GodotSceneImporter.js +767 -821
  297. package/dist/esm/import/LDtkImporter.js +415 -453
  298. package/dist/esm/import/Live2DImporter.js +477 -517
  299. package/dist/esm/import/NdgFormat.js +410 -456
  300. package/dist/esm/import/OgmoImporter.js +446 -492
  301. package/dist/esm/import/RPGMakerImporter.js +431 -476
  302. package/dist/esm/import/SceneImporter.js +385 -422
  303. package/dist/esm/import/SpineImporter.js +491 -545
  304. package/dist/esm/import/SpriterImporter.js +570 -612
  305. package/dist/esm/import/TiledMapImporter.js +790 -845
  306. package/dist/esm/import/UnitySceneImporter.js +666 -702
  307. package/dist/esm/import/index.js +247 -258
  308. package/dist/esm/index.js +1332 -188
  309. package/dist/esm/input/GamepadNavigation.js +187 -204
  310. package/dist/esm/input/InputManager.js +401 -420
  311. package/dist/esm/input/useGamepads.js +72 -80
  312. package/dist/esm/integration/IconSprite.js +143 -255
  313. package/dist/esm/inventory/InventorySystem.js +925 -994
  314. package/dist/esm/kids/KidMode.js +1003 -1021
  315. package/dist/esm/kids/KidTools.js +573 -593
  316. package/dist/esm/monetization/Monetization.js +180 -176
  317. package/dist/esm/multiplayer/LocalMultiplayer.js +290 -286
  318. package/dist/esm/multiplayer/MiniGameTypes.js +58 -58
  319. package/dist/esm/native-engine/AnimationSystem.js +735 -805
  320. package/dist/esm/native-engine/AssetPipeline.js +456 -514
  321. package/dist/esm/native-engine/AudioEngine.js +765 -803
  322. package/dist/esm/native-engine/InputSystem.js +1079 -1144
  323. package/dist/esm/native-engine/NetworkingSystem.js +740 -792
  324. package/dist/esm/native-engine/PhysicsEngine.js +585 -606
  325. package/dist/esm/native-engine/RenderingEngine.js +304 -349
  326. package/dist/esm/native-engine/SceneGraph.js +773 -807
  327. package/dist/esm/network/MultiplayerTransport.js +99 -131
  328. package/dist/esm/network/Networking.js +556 -563
  329. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/AbortController.js +22 -28
  330. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/AccessTokenHttpClient.js +41 -47
  331. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/DefaultHttpClient.js +36 -42
  332. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/DefaultReconnectPolicy.js +11 -14
  333. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Errors.js +111 -134
  334. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/FetchHttpClient.js +132 -157
  335. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HandshakeProtocol.js +40 -52
  336. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HeaderNames.js +6 -7
  337. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HttpClient.js +42 -47
  338. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HttpConnection.js +496 -571
  339. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HubConnection.js +828 -952
  340. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HubConnectionBuilder.js +126 -145
  341. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/IHubProtocol.js +14 -23
  342. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ILogger.js +12 -25
  343. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ITransport.js +15 -24
  344. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/JsonHubProtocol.js +109 -120
  345. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Loggers.js +11 -13
  346. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/LongPollingTransport.js +151 -184
  347. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/MessageBuffer.js +159 -195
  348. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ServerSentEventsTransport.js +91 -104
  349. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Subject.js +31 -34
  350. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/TextMessageFormat.js +17 -20
  351. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Utils.js +230 -248
  352. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/WebSocketTransport.js +136 -156
  353. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/XhrHttpClient.js +77 -84
  354. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/index.js +31 -12
  355. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/pkg-version.js +4 -3
  356. package/dist/esm/pathfinding/Pathfinding.js +249 -262
  357. package/dist/esm/performance/AssetStreaming.js +567 -634
  358. package/dist/esm/performance/BenchmarkSuite.js +285 -310
  359. package/dist/esm/performance/DeltaCompression.js +478 -525
  360. package/dist/esm/performance/DeterministicPhysics.js +479 -497
  361. package/dist/esm/performance/ECSOptimization.js +653 -694
  362. package/dist/esm/performance/GameSaveSystem.js +515 -555
  363. package/dist/esm/performance/HotReload.js +454 -499
  364. package/dist/esm/performance/InputRecording.js +520 -560
  365. package/dist/esm/performance/InterestManagement.js +460 -499
  366. package/dist/esm/performance/LocalizationRuntime.js +382 -422
  367. package/dist/esm/performance/MemoryManagement.js +415 -469
  368. package/dist/esm/performance/ModSupport.js +455 -495
  369. package/dist/esm/performance/MultiThreadedPhysics.js +408 -442
  370. package/dist/esm/performance/NetworkPrediction.js +436 -481
  371. package/dist/esm/performance/ObjectPooling.js +582 -616
  372. package/dist/esm/performance/Performance.js +182 -189
  373. package/dist/esm/performance/PerformanceAdvanced.js +621 -636
  374. package/dist/esm/performance/WebGPURenderer.js +660 -682
  375. package/dist/esm/physics/PhysicsAdvanced.js +359 -378
  376. package/dist/esm/physics/PhysicsEngine2D.js +393 -426
  377. package/dist/esm/plugins/PluginSDK.js +435 -465
  378. package/dist/esm/plugins/PluginTestKit.js +315 -329
  379. package/dist/esm/procedural/Procedural.js +248 -253
  380. package/dist/esm/procedural/WorldBuilding.js +316 -313
  381. package/dist/esm/quest/QuestSystem.js +982 -931
  382. package/dist/esm/release/MobileExport.js +163 -162
  383. package/dist/esm/release/Release.js +234 -237
  384. package/dist/esm/rendering/Camera2D.js +122 -123
  385. package/dist/esm/rendering/Renderer2D.js +323 -334
  386. package/dist/esm/rendering/WebGPURenderPipeline.js +647 -650
  387. package/dist/esm/runtime3d/Runtime3D.js +368 -377
  388. package/dist/esm/runtime3d/SceneEditor3D.js +268 -262
  389. package/dist/esm/scene/SceneManager.js +178 -192
  390. package/dist/esm/scripting/GraphToAST.js +576 -546
  391. package/dist/esm/scripting/LanguageExporter.js +263 -278
  392. package/dist/esm/scripting/NodeGraph.js +550 -569
  393. package/dist/esm/scripting/ScriptAST.js +45 -38
  394. package/dist/esm/scripting/VisualScripting2.js +1025 -1064
  395. package/dist/esm/scripting/exporters/CSharpExporter.js +465 -495
  396. package/dist/esm/scripting/exporters/GDScriptExporter.js +391 -441
  397. package/dist/esm/scripting/exporters/LuaExporter.js +407 -446
  398. package/dist/esm/scripting/exporters/PythonExporter.js +485 -548
  399. package/dist/esm/scripting/exporters/RustExporter.js +460 -511
  400. package/dist/esm/scripting/exporters/TypeScriptExporter.js +506 -555
  401. package/dist/esm/social/Social.js +77 -79
  402. package/dist/esm/systems/LightingSystem.js +855 -930
  403. package/dist/esm/systems/ParticleSystem2.js +1453 -1450
  404. package/dist/esm/systems/PhysicsDebugSystem.js +1078 -1140
  405. package/dist/esm/systems/TerrainSystem.js +996 -1097
  406. package/dist/esm/templates/ActionTemplates.js +307 -308
  407. package/dist/esm/templates/FightingTemplate.js +439 -462
  408. package/dist/esm/templates/MetroidvaniaTemplate.js +391 -404
  409. package/dist/esm/templates/PartyTemplates.js +206 -201
  410. package/dist/esm/templates/PuzzleTemplates.js +260 -260
  411. package/dist/esm/templates/RPGTemplates.js +172 -177
  412. package/dist/esm/templates/SportsTemplates.js +251 -249
  413. package/dist/esm/templates/StrategyTemplates.js +158 -152
  414. package/dist/esm/templates/SurvivalTemplate.js +367 -379
  415. package/dist/esm/templates/WaveDefense.js +501 -525
  416. package/dist/esm/tilemap/Tilemap.js +209 -213
  417. package/dist/esm/tutorials/TutorialBranching.js +399 -416
  418. package/dist/esm/tutorials/TutorialEngine.js +893 -930
  419. package/dist/esm/tutorials/TutorialOverlay.js +603 -639
  420. package/dist/esm/tutorials/content/Tutorials_T05_T08.js +792 -808
  421. package/dist/esm/tutorials/content/Tutorials_T09_T11.js +740 -755
  422. package/dist/esm/tutorials/content/Tutorials_T12_T15.js +759 -777
  423. package/dist/esm/ui/GameUI.js +296 -311
  424. package/dist/esm/unity-integration/UnityAssetStore.js +704 -740
  425. package/dist/esm/unity-integration/UnityImport.js +1071 -1175
  426. package/dist/esm/unity-integration/UnityLiveLink.js +938 -980
  427. package/dist/esm/unity-integration/components/UnityAssetStoreBrowser.js +1234 -756
  428. package/dist/esm/unity-integration/components/UnityProjectBrowser.js +1241 -767
  429. package/dist/esm/unreal-integration/UnrealImport.js +395 -411
  430. package/dist/esm/unreal-integration/UnrealLiveLink.js +1105 -1136
  431. package/dist/esm/unreal-integration/UnrealMarketplace.js +442 -472
  432. package/dist/esm/unreal-integration/components/UnrealProjectBrowser.js +1151 -766
  433. package/dist/esm/xr/ARVR.js +181 -174
  434. package/package.json +7 -12
@@ -1,1606 +1,1590 @@
1
- /**
2
- * @file ShaderGraph.ts
3
- * @description Visual Shader Graph Editor System
4
- * PRO-1.4: Professional Editor Features
5
- *
6
- * Features:
7
- * - Node-based shader editing
8
- * - GLSL/WGSL/HLSL generation
9
- * - Real-time preview
10
- * - Material templates
11
- * - Custom node creation
12
- * - Subgraph support
13
- * - PBR and unlit workflows
14
- */
15
- // ============================================================
16
- // Built-in Node Library
17
- // ============================================================
18
1
  const SHADER_NODE_LIBRARY = [
19
- // ─── Input Nodes ─────────────────────────────────────────
20
- {
21
- id: 'position',
22
- name: 'Position',
23
- category: 'input',
24
- description: 'World/Object/View position',
25
- inputs: [],
26
- outputs: [
27
- { name: 'World', type: 'vec3' },
28
- { name: 'Object', type: 'vec3' },
29
- { name: 'View', type: 'vec3' },
30
- { name: 'Tangent', type: 'vec3' },
31
- ],
32
- glsl: `
33
- vec3 {{output.World}} = v_worldPosition;
34
- vec3 {{output.Object}} = v_objectPosition;
35
- vec3 {{output.View}} = v_viewPosition;
36
- vec3 {{output.Tangent}} = v_tangent;
37
- `,
38
- },
39
- {
40
- id: 'normal',
41
- name: 'Normal',
42
- category: 'input',
43
- description: 'Surface normal vectors',
44
- inputs: [],
45
- outputs: [
46
- { name: 'World', type: 'vec3' },
47
- { name: 'Object', type: 'vec3' },
48
- { name: 'View', type: 'vec3' },
49
- { name: 'Tangent', type: 'vec3' },
50
- ],
51
- glsl: `
52
- vec3 {{output.World}} = normalize(v_worldNormal);
53
- vec3 {{output.Object}} = normalize(v_objectNormal);
54
- vec3 {{output.View}} = normalize(v_viewNormal);
55
- vec3 {{output.Tangent}} = normalize(v_tangentNormal);
56
- `,
57
- },
58
- {
59
- id: 'uv',
60
- name: 'UV',
61
- category: 'input',
62
- description: 'Texture coordinates',
63
- inputs: [],
64
- outputs: [
65
- { name: 'UV0', type: 'vec2' },
66
- { name: 'UV1', type: 'vec2' },
67
- { name: 'UV2', type: 'vec2' },
68
- { name: 'UV3', type: 'vec2' },
69
- ],
70
- glsl: `
71
- vec2 {{output.UV0}} = v_uv0;
72
- vec2 {{output.UV1}} = v_uv1;
73
- vec2 {{output.UV2}} = v_uv2;
74
- vec2 {{output.UV3}} = v_uv3;
75
- `,
76
- },
77
- {
78
- id: 'vertexColor',
79
- name: 'Vertex Color',
80
- category: 'input',
81
- description: 'Per-vertex color',
82
- inputs: [],
83
- outputs: [
84
- { name: 'Color', type: 'vec4' },
85
- { name: 'R', type: 'float' },
86
- { name: 'G', type: 'float' },
87
- { name: 'B', type: 'float' },
88
- { name: 'A', type: 'float' },
89
- ],
90
- glsl: `
91
- vec4 {{output.Color}} = v_color;
92
- float {{output.R}} = v_color.r;
93
- float {{output.G}} = v_color.g;
94
- float {{output.B}} = v_color.b;
95
- float {{output.A}} = v_color.a;
96
- `,
97
- },
98
- {
99
- id: 'time',
100
- name: 'Time',
101
- category: 'input',
102
- description: 'Time values for animation',
103
- inputs: [],
104
- outputs: [
105
- { name: 'Time', type: 'float' },
106
- { name: 'SinTime', type: 'float' },
107
- { name: 'CosTime', type: 'float' },
108
- { name: 'DeltaTime', type: 'float' },
109
- { name: 'SmoothDelta', type: 'float' },
110
- ],
111
- glsl: `
112
- float {{output.Time}} = u_time;
113
- float {{output.SinTime}} = sin(u_time);
114
- float {{output.CosTime}} = cos(u_time);
115
- float {{output.DeltaTime}} = u_deltaTime;
116
- float {{output.SmoothDelta}} = u_smoothDeltaTime;
117
- `,
118
- },
119
- {
120
- id: 'viewDirection',
121
- name: 'View Direction',
122
- category: 'input',
123
- description: 'Camera view direction',
124
- inputs: [],
125
- outputs: [
126
- { name: 'World', type: 'vec3' },
127
- { name: 'Object', type: 'vec3' },
128
- { name: 'View', type: 'vec3' },
129
- ],
130
- glsl: `
131
- vec3 {{output.World}} = normalize(u_cameraPosition - v_worldPosition);
132
- vec3 {{output.Object}} = (u_worldToObject * vec4({{output.World}}, 0.0)).xyz;
133
- vec3 {{output.View}} = (u_viewMatrix * vec4({{output.World}}, 0.0)).xyz;
134
- `,
135
- },
136
- {
137
- id: 'cameraPosition',
138
- name: 'Camera Position',
139
- category: 'input',
140
- inputs: [],
141
- outputs: [{ name: 'Position', type: 'vec3' }],
142
- glsl: `vec3 {{output.Position}} = u_cameraPosition;`,
143
- },
144
- {
145
- id: 'screenPosition',
146
- name: 'Screen Position',
147
- category: 'input',
148
- inputs: [],
149
- outputs: [
150
- { name: 'Default', type: 'vec4' },
151
- { name: 'Raw', type: 'vec4' },
152
- { name: 'Center', type: 'vec2' },
153
- { name: 'Tiled', type: 'vec2' },
154
- ],
155
- glsl: `
156
- vec4 {{output.Default}} = gl_FragCoord;
157
- vec4 {{output.Raw}} = gl_FragCoord;
158
- vec2 {{output.Center}} = gl_FragCoord.xy / u_resolution - 0.5;
159
- vec2 {{output.Tiled}} = fract(gl_FragCoord.xy / 256.0);
160
- `,
161
- },
162
- {
163
- id: 'constant',
164
- name: 'Constant',
165
- category: 'input',
166
- description: 'Constant value',
167
- inputs: [],
168
- outputs: [{ name: 'Out', type: 'float' }],
169
- properties: [{ name: 'Value', type: 'float', default: 0 }],
170
- glsl: `float {{output.Out}} = {{prop.Value}};`,
171
- },
172
- {
173
- id: 'color',
174
- name: 'Color',
175
- category: 'input',
176
- description: 'Color constant',
177
- inputs: [],
178
- outputs: [
179
- { name: 'Out', type: 'vec4' },
180
- { name: 'RGB', type: 'vec3' },
181
- { name: 'R', type: 'float' },
182
- { name: 'G', type: 'float' },
183
- { name: 'B', type: 'float' },
184
- { name: 'A', type: 'float' },
185
- ],
186
- properties: [{ name: 'Color', type: 'color', default: [1, 1, 1, 1] }],
187
- glsl: `
188
- vec4 {{output.Out}} = vec4({{prop.Color}});
189
- vec3 {{output.RGB}} = {{output.Out}}.rgb;
190
- float {{output.R}} = {{output.Out}}.r;
191
- float {{output.G}} = {{output.Out}}.g;
192
- float {{output.B}} = {{output.Out}}.b;
193
- float {{output.A}} = {{output.Out}}.a;
194
- `,
195
- },
196
- {
197
- id: 'vector2',
198
- name: 'Vector 2',
199
- category: 'input',
200
- inputs: [],
201
- outputs: [{ name: 'Out', type: 'vec2' }],
202
- properties: [{ name: 'Value', type: 'vec2', default: [0, 0] }],
203
- glsl: `vec2 {{output.Out}} = vec2({{prop.Value}});`,
204
- },
205
- {
206
- id: 'vector3',
207
- name: 'Vector 3',
208
- category: 'input',
209
- inputs: [],
210
- outputs: [{ name: 'Out', type: 'vec3' }],
211
- properties: [{ name: 'Value', type: 'vec3', default: [0, 0, 0] }],
212
- glsl: `vec3 {{output.Out}} = vec3({{prop.Value}});`,
213
- },
214
- {
215
- id: 'vector4',
216
- name: 'Vector 4',
217
- category: 'input',
218
- inputs: [],
219
- outputs: [{ name: 'Out', type: 'vec4' }],
220
- properties: [{ name: 'Value', type: 'vec4', default: [0, 0, 0, 0] }],
221
- glsl: `vec4 {{output.Out}} = vec4({{prop.Value}});`,
222
- },
223
- // ─── Math Nodes ──────────────────────────────────────────
224
- {
225
- id: 'add',
226
- name: 'Add',
227
- category: 'math',
228
- inputs: [
229
- { name: 'A', type: 'float', default: 0 },
230
- { name: 'B', type: 'float', default: 0 },
231
- ],
232
- outputs: [{ name: 'Out', type: 'float' }],
233
- glsl: `float {{output.Out}} = {{input.A}} + {{input.B}};`,
234
- },
235
- {
236
- id: 'subtract',
237
- name: 'Subtract',
238
- category: 'math',
239
- inputs: [
240
- { name: 'A', type: 'float', default: 0 },
241
- { name: 'B', type: 'float', default: 0 },
242
- ],
243
- outputs: [{ name: 'Out', type: 'float' }],
244
- glsl: `float {{output.Out}} = {{input.A}} - {{input.B}};`,
245
- },
246
- {
247
- id: 'multiply',
248
- name: 'Multiply',
249
- category: 'math',
250
- inputs: [
251
- { name: 'A', type: 'float', default: 1 },
252
- { name: 'B', type: 'float', default: 1 },
253
- ],
254
- outputs: [{ name: 'Out', type: 'float' }],
255
- glsl: `float {{output.Out}} = {{input.A}} * {{input.B}};`,
256
- },
257
- {
258
- id: 'divide',
259
- name: 'Divide',
260
- category: 'math',
261
- inputs: [
262
- { name: 'A', type: 'float', default: 1 },
263
- { name: 'B', type: 'float', default: 1 },
264
- ],
265
- outputs: [{ name: 'Out', type: 'float' }],
266
- glsl: `float {{output.Out}} = {{input.A}} / max({{input.B}}, 0.0001);`,
267
- },
268
- {
269
- id: 'power',
270
- name: 'Power',
271
- category: 'math',
272
- inputs: [
273
- { name: 'Base', type: 'float', default: 2 },
274
- { name: 'Exp', type: 'float', default: 2 },
275
- ],
276
- outputs: [{ name: 'Out', type: 'float' }],
277
- glsl: `float {{output.Out}} = pow({{input.Base}}, {{input.Exp}});`,
278
- },
279
- {
280
- id: 'sqrt',
281
- name: 'Square Root',
282
- category: 'math',
283
- inputs: [{ name: 'In', type: 'float', default: 1 }],
284
- outputs: [{ name: 'Out', type: 'float' }],
285
- glsl: `float {{output.Out}} = sqrt(max({{input.In}}, 0.0));`,
286
- },
287
- {
288
- id: 'abs',
289
- name: 'Absolute',
290
- category: 'math',
291
- inputs: [{ name: 'In', type: 'float', default: 0 }],
292
- outputs: [{ name: 'Out', type: 'float' }],
293
- glsl: `float {{output.Out}} = abs({{input.In}});`,
294
- },
295
- {
296
- id: 'negate',
297
- name: 'Negate',
298
- category: 'math',
299
- inputs: [{ name: 'In', type: 'float', default: 0 }],
300
- outputs: [{ name: 'Out', type: 'float' }],
301
- glsl: `float {{output.Out}} = -{{input.In}};`,
302
- },
303
- {
304
- id: 'min',
305
- name: 'Minimum',
306
- category: 'math',
307
- inputs: [
308
- { name: 'A', type: 'float', default: 0 },
309
- { name: 'B', type: 'float', default: 0 },
310
- ],
311
- outputs: [{ name: 'Out', type: 'float' }],
312
- glsl: `float {{output.Out}} = min({{input.A}}, {{input.B}});`,
313
- },
314
- {
315
- id: 'max',
316
- name: 'Maximum',
317
- category: 'math',
318
- inputs: [
319
- { name: 'A', type: 'float', default: 0 },
320
- { name: 'B', type: 'float', default: 0 },
321
- ],
322
- outputs: [{ name: 'Out', type: 'float' }],
323
- glsl: `float {{output.Out}} = max({{input.A}}, {{input.B}});`,
324
- },
325
- {
326
- id: 'clamp',
327
- name: 'Clamp',
328
- category: 'math',
329
- inputs: [
330
- { name: 'In', type: 'float', default: 0 },
331
- { name: 'Min', type: 'float', default: 0 },
332
- { name: 'Max', type: 'float', default: 1 },
333
- ],
334
- outputs: [{ name: 'Out', type: 'float' }],
335
- glsl: `float {{output.Out}} = clamp({{input.In}}, {{input.Min}}, {{input.Max}});`,
336
- },
337
- {
338
- id: 'saturate',
339
- name: 'Saturate',
340
- category: 'math',
341
- description: 'Clamp to 0-1 range',
342
- inputs: [{ name: 'In', type: 'float', default: 0 }],
343
- outputs: [{ name: 'Out', type: 'float' }],
344
- glsl: `float {{output.Out}} = clamp({{input.In}}, 0.0, 1.0);`,
345
- },
346
- {
347
- id: 'lerp',
348
- name: 'Lerp',
349
- category: 'math',
350
- description: 'Linear interpolation',
351
- inputs: [
352
- { name: 'A', type: 'float', default: 0 },
353
- { name: 'B', type: 'float', default: 1 },
354
- { name: 'T', type: 'float', default: 0.5 },
355
- ],
356
- outputs: [{ name: 'Out', type: 'float' }],
357
- glsl: `float {{output.Out}} = mix({{input.A}}, {{input.B}}, {{input.T}});`,
358
- },
359
- {
360
- id: 'smoothstep',
361
- name: 'Smoothstep',
362
- category: 'math',
363
- inputs: [
364
- { name: 'Edge0', type: 'float', default: 0 },
365
- { name: 'Edge1', type: 'float', default: 1 },
366
- { name: 'In', type: 'float', default: 0.5 },
367
- ],
368
- outputs: [{ name: 'Out', type: 'float' }],
369
- glsl: `float {{output.Out}} = smoothstep({{input.Edge0}}, {{input.Edge1}}, {{input.In}});`,
370
- },
371
- {
372
- id: 'step',
373
- name: 'Step',
374
- category: 'math',
375
- inputs: [
376
- { name: 'Edge', type: 'float', default: 0.5 },
377
- { name: 'In', type: 'float', default: 0 },
378
- ],
379
- outputs: [{ name: 'Out', type: 'float' }],
380
- glsl: `float {{output.Out}} = step({{input.Edge}}, {{input.In}});`,
381
- },
382
- {
383
- id: 'floor',
384
- name: 'Floor',
385
- category: 'math',
386
- inputs: [{ name: 'In', type: 'float', default: 0 }],
387
- outputs: [{ name: 'Out', type: 'float' }],
388
- glsl: `float {{output.Out}} = floor({{input.In}});`,
389
- },
390
- {
391
- id: 'ceil',
392
- name: 'Ceiling',
393
- category: 'math',
394
- inputs: [{ name: 'In', type: 'float', default: 0 }],
395
- outputs: [{ name: 'Out', type: 'float' }],
396
- glsl: `float {{output.Out}} = ceil({{input.In}});`,
397
- },
398
- {
399
- id: 'round',
400
- name: 'Round',
401
- category: 'math',
402
- inputs: [{ name: 'In', type: 'float', default: 0 }],
403
- outputs: [{ name: 'Out', type: 'float' }],
404
- glsl: `float {{output.Out}} = floor({{input.In}} + 0.5);`,
405
- },
406
- {
407
- id: 'frac',
408
- name: 'Fraction',
409
- category: 'math',
410
- inputs: [{ name: 'In', type: 'float', default: 0 }],
411
- outputs: [{ name: 'Out', type: 'float' }],
412
- glsl: `float {{output.Out}} = fract({{input.In}});`,
413
- },
414
- {
415
- id: 'mod',
416
- name: 'Modulo',
417
- category: 'math',
418
- inputs: [
419
- { name: 'A', type: 'float', default: 0 },
420
- { name: 'B', type: 'float', default: 1 },
421
- ],
422
- outputs: [{ name: 'Out', type: 'float' }],
423
- glsl: `float {{output.Out}} = mod({{input.A}}, {{input.B}});`,
424
- },
425
- {
426
- id: 'sin',
427
- name: 'Sine',
428
- category: 'math',
429
- inputs: [{ name: 'In', type: 'float', default: 0 }],
430
- outputs: [{ name: 'Out', type: 'float' }],
431
- glsl: `float {{output.Out}} = sin({{input.In}});`,
432
- },
433
- {
434
- id: 'cos',
435
- name: 'Cosine',
436
- category: 'math',
437
- inputs: [{ name: 'In', type: 'float', default: 0 }],
438
- outputs: [{ name: 'Out', type: 'float' }],
439
- glsl: `float {{output.Out}} = cos({{input.In}});`,
440
- },
441
- {
442
- id: 'tan',
443
- name: 'Tangent',
444
- category: 'math',
445
- inputs: [{ name: 'In', type: 'float', default: 0 }],
446
- outputs: [{ name: 'Out', type: 'float' }],
447
- glsl: `float {{output.Out}} = tan({{input.In}});`,
448
- },
449
- {
450
- id: 'asin',
451
- name: 'Arcsine',
452
- category: 'math',
453
- inputs: [{ name: 'In', type: 'float', default: 0 }],
454
- outputs: [{ name: 'Out', type: 'float' }],
455
- glsl: `float {{output.Out}} = asin(clamp({{input.In}}, -1.0, 1.0));`,
456
- },
457
- {
458
- id: 'acos',
459
- name: 'Arccosine',
460
- category: 'math',
461
- inputs: [{ name: 'In', type: 'float', default: 0 }],
462
- outputs: [{ name: 'Out', type: 'float' }],
463
- glsl: `float {{output.Out}} = acos(clamp({{input.In}}, -1.0, 1.0));`,
464
- },
465
- {
466
- id: 'atan',
467
- name: 'Arctangent',
468
- category: 'math',
469
- inputs: [{ name: 'In', type: 'float', default: 0 }],
470
- outputs: [{ name: 'Out', type: 'float' }],
471
- glsl: `float {{output.Out}} = atan({{input.In}});`,
472
- },
473
- {
474
- id: 'atan2',
475
- name: 'Arctangent2',
476
- category: 'math',
477
- inputs: [
478
- { name: 'Y', type: 'float', default: 0 },
479
- { name: 'X', type: 'float', default: 1 },
480
- ],
481
- outputs: [{ name: 'Out', type: 'float' }],
482
- glsl: `float {{output.Out}} = atan({{input.Y}}, {{input.X}});`,
483
- },
484
- {
485
- id: 'exp',
486
- name: 'Exponential',
487
- category: 'math',
488
- inputs: [{ name: 'In', type: 'float', default: 0 }],
489
- outputs: [{ name: 'Out', type: 'float' }],
490
- glsl: `float {{output.Out}} = exp({{input.In}});`,
491
- },
492
- {
493
- id: 'exp2',
494
- name: 'Exponential 2',
495
- category: 'math',
496
- inputs: [{ name: 'In', type: 'float', default: 0 }],
497
- outputs: [{ name: 'Out', type: 'float' }],
498
- glsl: `float {{output.Out}} = exp2({{input.In}});`,
499
- },
500
- {
501
- id: 'log',
502
- name: 'Logarithm',
503
- category: 'math',
504
- inputs: [{ name: 'In', type: 'float', default: 1 }],
505
- outputs: [{ name: 'Out', type: 'float' }],
506
- glsl: `float {{output.Out}} = log(max({{input.In}}, 0.0001));`,
507
- },
508
- {
509
- id: 'log2',
510
- name: 'Logarithm 2',
511
- category: 'math',
512
- inputs: [{ name: 'In', type: 'float', default: 1 }],
513
- outputs: [{ name: 'Out', type: 'float' }],
514
- glsl: `float {{output.Out}} = log2(max({{input.In}}, 0.0001));`,
515
- },
516
- {
517
- id: 'oneMinus',
518
- name: 'One Minus',
519
- category: 'math',
520
- inputs: [{ name: 'In', type: 'float', default: 0 }],
521
- outputs: [{ name: 'Out', type: 'float' }],
522
- glsl: `float {{output.Out}} = 1.0 - {{input.In}};`,
523
- },
524
- {
525
- id: 'remap',
526
- name: 'Remap',
527
- category: 'math',
528
- description: 'Remap value from one range to another',
529
- inputs: [
530
- { name: 'In', type: 'float', default: 0 },
531
- { name: 'InMin', type: 'float', default: 0 },
532
- { name: 'InMax', type: 'float', default: 1 },
533
- { name: 'OutMin', type: 'float', default: 0 },
534
- { name: 'OutMax', type: 'float', default: 1 },
535
- ],
536
- outputs: [{ name: 'Out', type: 'float' }],
537
- glsl: `
538
- float {{output.Out}} = {{input.OutMin}} + ({{input.In}} - {{input.InMin}}) * ({{input.OutMax}} - {{input.OutMin}}) / ({{input.InMax}} - {{input.InMin}});
539
- `,
540
- },
541
- // ─── Vector Nodes ────────────────────────────────────────
542
- {
543
- id: 'vectorSplit',
544
- name: 'Split',
545
- category: 'vector',
546
- description: 'Split vector into components',
547
- inputs: [{ name: 'In', type: 'vec4', default: [0, 0, 0, 0] }],
548
- outputs: [
549
- { name: 'X', type: 'float' },
550
- { name: 'Y', type: 'float' },
551
- { name: 'Z', type: 'float' },
552
- { name: 'W', type: 'float' },
553
- ],
554
- glsl: `
555
- float {{output.X}} = {{input.In}}.x;
556
- float {{output.Y}} = {{input.In}}.y;
557
- float {{output.Z}} = {{input.In}}.z;
558
- float {{output.W}} = {{input.In}}.w;
559
- `,
560
- },
561
- {
562
- id: 'vectorCombine',
563
- name: 'Combine',
564
- category: 'vector',
565
- description: 'Combine components into vector',
566
- inputs: [
567
- { name: 'X', type: 'float', default: 0 },
568
- { name: 'Y', type: 'float', default: 0 },
569
- { name: 'Z', type: 'float', default: 0 },
570
- { name: 'W', type: 'float', default: 0 },
571
- ],
572
- outputs: [
573
- { name: 'XYZW', type: 'vec4' },
574
- { name: 'XYZ', type: 'vec3' },
575
- { name: 'XY', type: 'vec2' },
576
- ],
577
- glsl: `
578
- vec4 {{output.XYZW}} = vec4({{input.X}}, {{input.Y}}, {{input.Z}}, {{input.W}});
579
- vec3 {{output.XYZ}} = vec3({{input.X}}, {{input.Y}}, {{input.Z}});
580
- vec2 {{output.XY}} = vec2({{input.X}}, {{input.Y}});
581
- `,
582
- },
583
- {
584
- id: 'dot',
585
- name: 'Dot Product',
586
- category: 'vector',
587
- inputs: [
588
- { name: 'A', type: 'vec3', default: [1, 0, 0] },
589
- { name: 'B', type: 'vec3', default: [0, 1, 0] },
590
- ],
591
- outputs: [{ name: 'Out', type: 'float' }],
592
- glsl: `float {{output.Out}} = dot({{input.A}}, {{input.B}});`,
593
- },
594
- {
595
- id: 'cross',
596
- name: 'Cross Product',
597
- category: 'vector',
598
- inputs: [
599
- { name: 'A', type: 'vec3', default: [1, 0, 0] },
600
- { name: 'B', type: 'vec3', default: [0, 1, 0] },
601
- ],
602
- outputs: [{ name: 'Out', type: 'vec3' }],
603
- glsl: `vec3 {{output.Out}} = cross({{input.A}}, {{input.B}});`,
604
- },
605
- {
606
- id: 'normalize',
607
- name: 'Normalize',
608
- category: 'vector',
609
- inputs: [{ name: 'In', type: 'vec3', default: [1, 0, 0] }],
610
- outputs: [{ name: 'Out', type: 'vec3' }],
611
- glsl: `vec3 {{output.Out}} = normalize({{input.In}});`,
612
- },
613
- {
614
- id: 'length',
615
- name: 'Length',
616
- category: 'vector',
617
- inputs: [{ name: 'In', type: 'vec3', default: [1, 0, 0] }],
618
- outputs: [{ name: 'Out', type: 'float' }],
619
- glsl: `float {{output.Out}} = length({{input.In}});`,
620
- },
621
- {
622
- id: 'distance',
623
- name: 'Distance',
624
- category: 'vector',
625
- inputs: [
626
- { name: 'A', type: 'vec3', default: [0, 0, 0] },
627
- { name: 'B', type: 'vec3', default: [1, 0, 0] },
628
- ],
629
- outputs: [{ name: 'Out', type: 'float' }],
630
- glsl: `float {{output.Out}} = distance({{input.A}}, {{input.B}});`,
631
- },
632
- {
633
- id: 'reflect',
634
- name: 'Reflect',
635
- category: 'vector',
636
- inputs: [
637
- { name: 'In', type: 'vec3', default: [1, 0, 0] },
638
- { name: 'Normal', type: 'vec3', default: [0, 1, 0] },
639
- ],
640
- outputs: [{ name: 'Out', type: 'vec3' }],
641
- glsl: `vec3 {{output.Out}} = reflect({{input.In}}, {{input.Normal}});`,
642
- },
643
- {
644
- id: 'refract',
645
- name: 'Refract',
646
- category: 'vector',
647
- inputs: [
648
- { name: 'In', type: 'vec3', default: [1, 0, 0] },
649
- { name: 'Normal', type: 'vec3', default: [0, 1, 0] },
650
- { name: 'IOR', type: 'float', default: 1.5 },
651
- ],
652
- outputs: [{ name: 'Out', type: 'vec3' }],
653
- glsl: `vec3 {{output.Out}} = refract({{input.In}}, {{input.Normal}}, 1.0 / {{input.IOR}});`,
654
- },
655
- // ─── Texture Nodes ───────────────────────────────────────
656
- {
657
- id: 'sampleTexture2D',
658
- name: 'Sample Texture 2D',
659
- category: 'texture',
660
- inputs: [{ name: 'UV', type: 'vec2', default: [0, 0] }],
661
- outputs: [
662
- { name: 'RGBA', type: 'vec4' },
663
- { name: 'RGB', type: 'vec3' },
664
- { name: 'R', type: 'float' },
665
- { name: 'G', type: 'float' },
666
- { name: 'B', type: 'float' },
667
- { name: 'A', type: 'float' },
668
- ],
669
- properties: [{ name: 'Texture', type: 'texture', default: null }],
670
- glsl: `
671
- vec4 {{output.RGBA}} = texture({{prop.Texture}}, {{input.UV}});
672
- vec3 {{output.RGB}} = {{output.RGBA}}.rgb;
673
- float {{output.R}} = {{output.RGBA}}.r;
674
- float {{output.G}} = {{output.RGBA}}.g;
675
- float {{output.B}} = {{output.RGBA}}.b;
676
- float {{output.A}} = {{output.RGBA}}.a;
677
- `,
678
- },
679
- {
680
- id: 'sampleNormalMap',
681
- name: 'Sample Normal Map',
682
- category: 'texture',
683
- inputs: [
684
- { name: 'UV', type: 'vec2', default: [0, 0] },
685
- { name: 'Strength', type: 'float', default: 1 },
686
- ],
687
- outputs: [{ name: 'Normal', type: 'vec3' }],
688
- properties: [{ name: 'Texture', type: 'texture', default: null }],
689
- glsl: `
690
- vec3 normalSample = texture({{prop.Texture}}, {{input.UV}}).rgb * 2.0 - 1.0;
691
- normalSample.xy *= {{input.Strength}};
692
- vec3 {{output.Normal}} = normalize(normalSample);
693
- `,
694
- },
695
- {
696
- id: 'sampleCubemap',
697
- name: 'Sample Cubemap',
698
- category: 'texture',
699
- inputs: [{ name: 'Direction', type: 'vec3', default: [0, 1, 0] }],
700
- outputs: [{ name: 'RGBA', type: 'vec4' }],
701
- properties: [{ name: 'Cubemap', type: 'texture', default: null }],
702
- glsl: `vec4 {{output.RGBA}} = textureCube({{prop.Cubemap}}, {{input.Direction}});`,
703
- },
704
- {
705
- id: 'triplanar',
706
- name: 'Triplanar Mapping',
707
- category: 'texture',
708
- description: 'Sample texture using world position and normal',
709
- inputs: [
710
- { name: 'Position', type: 'vec3' },
711
- { name: 'Normal', type: 'vec3' },
712
- { name: 'Tile', type: 'float', default: 1 },
713
- { name: 'Blend', type: 'float', default: 1 },
714
- ],
715
- outputs: [{ name: 'RGBA', type: 'vec4' }],
716
- properties: [{ name: 'Texture', type: 'texture', default: null }],
717
- glsl: `
718
- vec3 blending = pow(abs({{input.Normal}}), vec3({{input.Blend}}));
719
- blending /= dot(blending, vec3(1.0));
720
-
721
- vec4 xProject = texture({{prop.Texture}}, {{input.Position}}.yz * {{input.Tile}});
722
- vec4 yProject = texture({{prop.Texture}}, {{input.Position}}.xz * {{input.Tile}});
723
- vec4 zProject = texture({{prop.Texture}}, {{input.Position}}.xy * {{input.Tile}});
724
-
725
- vec4 {{output.RGBA}} = xProject * blending.x + yProject * blending.y + zProject * blending.z;
726
- `,
727
- },
728
- // ─── UV Nodes ────────────────────────────────────────────
729
- {
730
- id: 'tiling',
731
- name: 'Tiling and Offset',
732
- category: 'uv',
733
- inputs: [
734
- { name: 'UV', type: 'vec2', default: [0, 0] },
735
- { name: 'Tiling', type: 'vec2', default: [1, 1] },
736
- { name: 'Offset', type: 'vec2', default: [0, 0] },
737
- ],
738
- outputs: [{ name: 'Out', type: 'vec2' }],
739
- glsl: `vec2 {{output.Out}} = {{input.UV}} * {{input.Tiling}} + {{input.Offset}};`,
740
- },
741
- {
742
- id: 'rotate',
743
- name: 'Rotate',
744
- category: 'uv',
745
- inputs: [
746
- { name: 'UV', type: 'vec2', default: [0, 0] },
747
- { name: 'Center', type: 'vec2', default: [0.5, 0.5] },
748
- { name: 'Rotation', type: 'float', default: 0 },
749
- ],
750
- outputs: [{ name: 'Out', type: 'vec2' }],
751
- glsl: `
752
- vec2 uvCentered = {{input.UV}} - {{input.Center}};
753
- float c = cos({{input.Rotation}});
754
- float s = sin({{input.Rotation}});
755
- vec2 {{output.Out}} = vec2(uvCentered.x * c - uvCentered.y * s, uvCentered.x * s + uvCentered.y * c) + {{input.Center}};
756
- `,
757
- },
758
- {
759
- id: 'flipbook',
760
- name: 'Flipbook',
761
- category: 'uv',
762
- description: 'Animated sprite sheet UV',
763
- inputs: [
764
- { name: 'UV', type: 'vec2', default: [0, 0] },
765
- { name: 'Width', type: 'float', default: 4 },
766
- { name: 'Height', type: 'float', default: 4 },
767
- { name: 'Tile', type: 'float', default: 0 },
768
- ],
769
- outputs: [{ name: 'Out', type: 'vec2' }],
770
- glsl: `
771
- float tile = floor({{input.Tile}});
772
- float invWidth = 1.0 / {{input.Width}};
773
- float invHeight = 1.0 / {{input.Height}};
774
- float tileX = mod(tile, {{input.Width}});
775
- float tileY = floor(tile * invWidth);
776
- vec2 {{output.Out}} = ({{input.UV}} + vec2(tileX, tileY)) * vec2(invWidth, invHeight);
777
- `,
778
- },
779
- {
780
- id: 'polar',
781
- name: 'Polar Coordinates',
782
- category: 'uv',
783
- inputs: [
784
- { name: 'UV', type: 'vec2', default: [0, 0] },
785
- { name: 'Center', type: 'vec2', default: [0.5, 0.5] },
786
- { name: 'RadialScale', type: 'float', default: 1 },
787
- { name: 'LengthScale', type: 'float', default: 1 },
788
- ],
789
- outputs: [{ name: 'Out', type: 'vec2' }],
790
- glsl: `
791
- vec2 delta = {{input.UV}} - {{input.Center}};
792
- float radius = length(delta) * 2.0 * {{input.LengthScale}};
793
- float angle = atan(delta.y, delta.x) / 6.283185 + 0.5;
794
- vec2 {{output.Out}} = vec2(radius, angle * {{input.RadialScale}});
795
- `,
796
- },
797
- {
798
- id: 'spherize',
799
- name: 'Spherize',
800
- category: 'uv',
801
- inputs: [
802
- { name: 'UV', type: 'vec2', default: [0, 0] },
803
- { name: 'Center', type: 'vec2', default: [0.5, 0.5] },
804
- { name: 'Strength', type: 'float', default: 0.5 },
805
- { name: 'Offset', type: 'vec2', default: [0, 0] },
806
- ],
807
- outputs: [{ name: 'Out', type: 'vec2' }],
808
- glsl: `
809
- vec2 delta = {{input.UV}} - {{input.Center}};
810
- float dist = length(delta);
811
- float factor = 1.0 + dist * dist * {{input.Strength}};
812
- vec2 {{output.Out}} = {{input.Center}} + delta / factor + {{input.Offset}};
813
- `,
814
- },
815
- {
816
- id: 'twirl',
817
- name: 'Twirl',
818
- category: 'uv',
819
- inputs: [
820
- { name: 'UV', type: 'vec2', default: [0, 0] },
821
- { name: 'Center', type: 'vec2', default: [0.5, 0.5] },
822
- { name: 'Strength', type: 'float', default: 1 },
823
- { name: 'Offset', type: 'vec2', default: [0, 0] },
824
- ],
825
- outputs: [{ name: 'Out', type: 'vec2' }],
826
- glsl: `
827
- vec2 delta = {{input.UV}} - {{input.Center}};
828
- float dist = length(delta);
829
- float angle = {{input.Strength}} * dist;
830
- float c = cos(angle);
831
- float s = sin(angle);
832
- vec2 {{output.Out}} = vec2(delta.x * c - delta.y * s, delta.x * s + delta.y * c) + {{input.Center}} + {{input.Offset}};
833
- `,
834
- },
835
- {
836
- id: 'parallax',
837
- name: 'Parallax Mapping',
838
- category: 'uv',
839
- inputs: [
840
- { name: 'UV', type: 'vec2', default: [0, 0] },
841
- { name: 'Height', type: 'float', default: 0.5 },
842
- { name: 'ViewDir', type: 'vec3' },
843
- { name: 'Amplitude', type: 'float', default: 0.05 },
844
- ],
845
- outputs: [{ name: 'Out', type: 'vec2' }],
846
- glsl: `
847
- float h = {{input.Height}};
848
- vec2 {{output.Out}} = {{input.UV}} - {{input.ViewDir}}.xy * (h * {{input.Amplitude}});
849
- `,
850
- },
851
- // ─── Color Nodes ─────────────────────────────────────────
852
- {
853
- id: 'blend',
854
- name: 'Blend',
855
- category: 'color',
856
- description: 'Blend two colors',
857
- inputs: [
858
- { name: 'Base', type: 'vec4', default: [0, 0, 0, 1] },
859
- { name: 'Blend', type: 'vec4', default: [1, 1, 1, 1] },
860
- { name: 'Opacity', type: 'float', default: 1 },
861
- ],
862
- outputs: [{ name: 'Out', type: 'vec4' }],
863
- properties: [
864
- {
865
- name: 'Mode',
866
- type: 'dropdown',
867
- default: 'normal',
868
- options: [
869
- 'normal',
870
- 'multiply',
871
- 'screen',
872
- 'overlay',
873
- 'add',
874
- 'subtract',
875
- 'difference',
876
- 'darken',
877
- 'lighten',
878
- ],
879
- },
880
- ],
881
- glsl: `
882
- vec4 {{output.Out}};
883
- // Blend mode logic here based on prop.Mode
884
- {{output.Out}} = mix({{input.Base}}, {{input.Blend}}, {{input.Opacity}});
885
- `,
886
- },
887
- {
888
- id: 'contrast',
889
- name: 'Contrast',
890
- category: 'color',
891
- inputs: [
892
- { name: 'In', type: 'vec3', default: [0.5, 0.5, 0.5] },
893
- { name: 'Contrast', type: 'float', default: 1 },
894
- ],
895
- outputs: [{ name: 'Out', type: 'vec3' }],
896
- glsl: `vec3 {{output.Out}} = ({{input.In}} - 0.5) * {{input.Contrast}} + 0.5;`,
897
- },
898
- {
899
- id: 'saturation',
900
- name: 'Saturation',
901
- category: 'color',
902
- inputs: [
903
- { name: 'In', type: 'vec3', default: [0.5, 0.5, 0.5] },
904
- { name: 'Saturation', type: 'float', default: 1 },
905
- ],
906
- outputs: [{ name: 'Out', type: 'vec3' }],
907
- glsl: `
908
- float luma = dot({{input.In}}, vec3(0.2126, 0.7152, 0.0722));
909
- vec3 {{output.Out}} = mix(vec3(luma), {{input.In}}, {{input.Saturation}});
910
- `,
911
- },
912
- {
913
- id: 'hue',
914
- name: 'Hue',
915
- category: 'color',
916
- inputs: [
917
- { name: 'In', type: 'vec3', default: [1, 0, 0] },
918
- { name: 'Offset', type: 'float', default: 0 },
919
- ],
920
- outputs: [{ name: 'Out', type: 'vec3' }],
921
- glsl: `
922
- // RGB to HSV
923
- vec3 hsvIn = {{input.In}};
924
- float maxC = max(max(hsvIn.r, hsvIn.g), hsvIn.b);
925
- float minC = min(min(hsvIn.r, hsvIn.g), hsvIn.b);
926
- float delta = maxC - minC;
927
- float h = 0.0;
928
- if (delta > 0.0) {
929
- if (maxC == hsvIn.r) h = mod((hsvIn.g - hsvIn.b) / delta, 6.0);
930
- else if (maxC == hsvIn.g) h = (hsvIn.b - hsvIn.r) / delta + 2.0;
931
- else h = (hsvIn.r - hsvIn.g) / delta + 4.0;
932
- h /= 6.0;
933
- }
934
- float s = maxC > 0.0 ? delta / maxC : 0.0;
935
- float v = maxC;
936
-
937
- // Shift hue
938
- h = fract(h + {{input.Offset}});
939
-
940
- // HSV to RGB
941
- float i = floor(h * 6.0);
942
- float f = h * 6.0 - i;
943
- float p = v * (1.0 - s);
944
- float q = v * (1.0 - f * s);
945
- float t = v * (1.0 - (1.0 - f) * s);
946
-
947
- vec3 {{output.Out}};
948
- int im = int(mod(i, 6.0));
949
- if (im == 0) {{output.Out}} = vec3(v, t, p);
950
- else if (im == 1) {{output.Out}} = vec3(q, v, p);
951
- else if (im == 2) {{output.Out}} = vec3(p, v, t);
952
- else if (im == 3) {{output.Out}} = vec3(p, q, v);
953
- else if (im == 4) {{output.Out}} = vec3(t, p, v);
954
- else {{output.Out}} = vec3(v, p, q);
955
- `,
956
- },
957
- {
958
- id: 'brightness',
959
- name: 'Brightness',
960
- category: 'color',
961
- inputs: [
962
- { name: 'In', type: 'vec3', default: [0.5, 0.5, 0.5] },
963
- { name: 'Brightness', type: 'float', default: 0 },
964
- ],
965
- outputs: [{ name: 'Out', type: 'vec3' }],
966
- glsl: `vec3 {{output.Out}} = {{input.In}} + {{input.Brightness}};`,
967
- },
968
- {
969
- id: 'whiteBalance',
970
- name: 'White Balance',
971
- category: 'color',
972
- inputs: [
973
- { name: 'In', type: 'vec3', default: [1, 1, 1] },
974
- { name: 'Temperature', type: 'float', default: 0 },
975
- { name: 'Tint', type: 'float', default: 0 },
976
- ],
977
- outputs: [{ name: 'Out', type: 'vec3' }],
978
- glsl: `
979
- float t = {{input.Temperature}};
980
- float ti = {{input.Tint}};
981
- vec3 {{output.Out}} = {{input.In}} + vec3(t, ti, -t);
982
- `,
983
- },
984
- {
985
- id: 'channelMixer',
986
- name: 'Channel Mixer',
987
- category: 'color',
988
- inputs: [{ name: 'In', type: 'vec3', default: [1, 1, 1] }],
989
- outputs: [{ name: 'Out', type: 'vec3' }],
990
- properties: [
991
- { name: 'Red', type: 'vec3', default: [1, 0, 0] },
992
- { name: 'Green', type: 'vec3', default: [0, 1, 0] },
993
- { name: 'Blue', type: 'vec3', default: [0, 0, 1] },
994
- ],
995
- glsl: `
996
- vec3 {{output.Out}} = vec3(
997
- dot({{input.In}}, vec3({{prop.Red}})),
998
- dot({{input.In}}, vec3({{prop.Green}})),
999
- dot({{input.In}}, vec3({{prop.Blue}}))
1000
- );
1001
- `,
1002
- },
1003
- {
1004
- id: 'colorGrade',
1005
- name: 'Color Grade',
1006
- category: 'color',
1007
- description: 'Lift-Gamma-Gain color grading',
1008
- inputs: [{ name: 'In', type: 'vec3', default: [0.5, 0.5, 0.5] }],
1009
- outputs: [{ name: 'Out', type: 'vec3' }],
1010
- properties: [
1011
- { name: 'Lift', type: 'color', default: [0, 0, 0, 1] },
1012
- { name: 'Gamma', type: 'color', default: [0.5, 0.5, 0.5, 1] },
1013
- { name: 'Gain', type: 'color', default: [1, 1, 1, 1] },
1014
- ],
1015
- glsl: `
1016
- vec3 lift = vec3({{prop.Lift}}.rgb);
1017
- vec3 gamma = vec3({{prop.Gamma}}.rgb);
1018
- vec3 gain = vec3({{prop.Gain}}.rgb);
1019
- vec3 col = {{input.In}} * gain + lift;
1020
- vec3 {{output.Out}} = pow(col, 1.0 / (gamma * 2.0));
1021
- `,
1022
- },
1023
- // ─── Lighting Nodes ──────────────────────────────────────
1024
- {
1025
- id: 'lambertDiffuse',
1026
- name: 'Lambert Diffuse',
1027
- category: 'lighting',
1028
- inputs: [
1029
- { name: 'Normal', type: 'vec3' },
1030
- { name: 'LightDir', type: 'vec3' },
1031
- { name: 'LightColor', type: 'vec3', default: [1, 1, 1] },
1032
- ],
1033
- outputs: [{ name: 'Out', type: 'vec3' }],
1034
- glsl: `
1035
- float ndotl = max(dot({{input.Normal}}, {{input.LightDir}}), 0.0);
1036
- vec3 {{output.Out}} = {{input.LightColor}} * ndotl;
1037
- `,
1038
- },
1039
- {
1040
- id: 'blinnPhongSpecular',
1041
- name: 'Blinn-Phong Specular',
1042
- category: 'lighting',
1043
- inputs: [
1044
- { name: 'Normal', type: 'vec3' },
1045
- { name: 'ViewDir', type: 'vec3' },
1046
- { name: 'LightDir', type: 'vec3' },
1047
- { name: 'Smoothness', type: 'float', default: 0.5 },
1048
- ],
1049
- outputs: [{ name: 'Out', type: 'float' }],
1050
- glsl: `
1051
- vec3 halfDir = normalize({{input.LightDir}} + {{input.ViewDir}});
1052
- float ndoth = max(dot({{input.Normal}}, halfDir), 0.0);
1053
- float spec = pow(ndoth, exp2(10.0 * {{input.Smoothness}} + 1.0));
1054
- float {{output.Out}} = spec;
1055
- `,
1056
- },
1057
- {
1058
- id: 'fresnel',
1059
- name: 'Fresnel',
1060
- category: 'lighting',
1061
- inputs: [
1062
- { name: 'Normal', type: 'vec3' },
1063
- { name: 'ViewDir', type: 'vec3' },
1064
- { name: 'Power', type: 'float', default: 5 },
1065
- ],
1066
- outputs: [{ name: 'Out', type: 'float' }],
1067
- glsl: `
1068
- float ndotv = max(dot({{input.Normal}}, {{input.ViewDir}}), 0.0);
1069
- float {{output.Out}} = pow(1.0 - ndotv, {{input.Power}});
1070
- `,
1071
- },
1072
- {
1073
- id: 'ambientOcclusion',
1074
- name: 'Ambient Occlusion',
1075
- category: 'lighting',
1076
- inputs: [
1077
- { name: 'Color', type: 'vec3' },
1078
- { name: 'AO', type: 'float', default: 1 },
1079
- { name: 'Intensity', type: 'float', default: 1 },
1080
- ],
1081
- outputs: [{ name: 'Out', type: 'vec3' }],
1082
- glsl: `vec3 {{output.Out}} = {{input.Color}} * mix(1.0, {{input.AO}}, {{input.Intensity}});`,
1083
- },
1084
- // ─── Procedural Nodes ────────────────────────────────────
1085
- {
1086
- id: 'noise',
1087
- name: 'Simple Noise',
1088
- category: 'procedural',
1089
- inputs: [
1090
- { name: 'UV', type: 'vec2', default: [0, 0] },
1091
- { name: 'Scale', type: 'float', default: 10 },
1092
- ],
1093
- outputs: [{ name: 'Out', type: 'float' }],
1094
- glsl: `
1095
- vec2 p = {{input.UV}} * {{input.Scale}};
1096
- float {{output.Out}} = fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
1097
- `,
1098
- },
1099
- {
1100
- id: 'gradient',
1101
- name: 'Gradient Noise',
1102
- category: 'procedural',
1103
- inputs: [
1104
- { name: 'UV', type: 'vec2', default: [0, 0] },
1105
- { name: 'Scale', type: 'float', default: 5 },
1106
- ],
1107
- outputs: [{ name: 'Out', type: 'float' }],
1108
- glsl: `
1109
- // Simple gradient noise approximation
1110
- vec2 p = {{input.UV}} * {{input.Scale}};
1111
- vec2 i = floor(p);
1112
- vec2 f = fract(p);
1113
- f = f * f * (3.0 - 2.0 * f);
1114
-
1115
- float a = fract(sin(dot(i, vec2(12.9898, 78.233))) * 43758.5453);
1116
- float b = fract(sin(dot(i + vec2(1.0, 0.0), vec2(12.9898, 78.233))) * 43758.5453);
1117
- float c = fract(sin(dot(i + vec2(0.0, 1.0), vec2(12.9898, 78.233))) * 43758.5453);
1118
- float d = fract(sin(dot(i + vec2(1.0, 1.0), vec2(12.9898, 78.233))) * 43758.5453);
1119
-
1120
- float {{output.Out}} = mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
1121
- `,
1122
- },
1123
- {
1124
- id: 'voronoi',
1125
- name: 'Voronoi',
1126
- category: 'procedural',
1127
- inputs: [
1128
- { name: 'UV', type: 'vec2', default: [0, 0] },
1129
- { name: 'Scale', type: 'float', default: 5 },
1130
- { name: 'Angle', type: 'float', default: 0 },
1131
- ],
1132
- outputs: [
1133
- { name: 'Out', type: 'float' },
1134
- { name: 'Cells', type: 'float' },
1135
- ],
1136
- glsl: `
1137
- vec2 p = {{input.UV}} * {{input.Scale}};
1138
- vec2 n = floor(p);
1139
- vec2 f = fract(p);
1140
-
1141
- float minDist = 1.0;
1142
- vec2 minCell = vec2(0.0);
1143
-
1144
- for (int j = -1; j <= 1; j++) {
1145
- for (int i = -1; i <= 1; i++) {
1146
- vec2 g = vec2(float(i), float(j));
1147
- vec2 o = fract(sin(vec2(dot(n + g, vec2(12.9898, 78.233)), dot(n + g, vec2(23.4321, 14.5678)))) * 43758.5453);
1148
- vec2 r = g + o - f;
1149
- float d = dot(r, r);
1150
- if (d < minDist) {
1151
- minDist = d;
1152
- minCell = n + g + o;
1153
- }
1154
- }
1155
- }
1156
-
1157
- float {{output.Out}} = minDist;
1158
- float {{output.Cells}} = fract(sin(dot(minCell, vec2(12.9898, 78.233))) * 43758.5453);
1159
- `,
1160
- },
1161
- {
1162
- id: 'checkerboard',
1163
- name: 'Checkerboard',
1164
- category: 'procedural',
1165
- inputs: [
1166
- { name: 'UV', type: 'vec2', default: [0, 0] },
1167
- { name: 'Frequency', type: 'vec2', default: [4, 4] },
1168
- ],
1169
- outputs: [{ name: 'Out', type: 'float' }],
1170
- properties: [
1171
- { name: 'ColorA', type: 'color', default: [1, 1, 1, 1] },
1172
- { name: 'ColorB', type: 'color', default: [0, 0, 0, 1] },
1173
- ],
1174
- glsl: `
1175
- vec2 uv = {{input.UV}} * {{input.Frequency}};
1176
- float c = mod(floor(uv.x) + floor(uv.y), 2.0);
1177
- float {{output.Out}} = c;
1178
- `,
1179
- },
1180
- {
1181
- id: 'ellipse',
1182
- name: 'Ellipse',
1183
- category: 'procedural',
1184
- inputs: [
1185
- { name: 'UV', type: 'vec2', default: [0, 0] },
1186
- { name: 'Width', type: 'float', default: 0.5 },
1187
- { name: 'Height', type: 'float', default: 0.5 },
1188
- ],
1189
- outputs: [{ name: 'Out', type: 'float' }],
1190
- glsl: `
1191
- vec2 d = {{input.UV}} - 0.5;
1192
- d.x /= {{input.Width}};
1193
- d.y /= {{input.Height}};
1194
- float {{output.Out}} = 1.0 - smoothstep(0.5, 0.51, length(d));
1195
- `,
1196
- },
1197
- {
1198
- id: 'rectangle',
1199
- name: 'Rectangle',
1200
- category: 'procedural',
1201
- inputs: [
1202
- { name: 'UV', type: 'vec2', default: [0, 0] },
1203
- { name: 'Width', type: 'float', default: 0.5 },
1204
- { name: 'Height', type: 'float', default: 0.5 },
1205
- ],
1206
- outputs: [{ name: 'Out', type: 'float' }],
1207
- glsl: `
1208
- vec2 d = abs({{input.UV}} - 0.5);
1209
- float {{output.Out}} = 1.0 - smoothstep(0.0, 0.01, max(d.x - {{input.Width}} * 0.5, d.y - {{input.Height}} * 0.5));
1210
- `,
1211
- },
1212
- {
1213
- id: 'roundedRectangle',
1214
- name: 'Rounded Rectangle',
1215
- category: 'procedural',
1216
- inputs: [
1217
- { name: 'UV', type: 'vec2', default: [0, 0] },
1218
- { name: 'Width', type: 'float', default: 0.5 },
1219
- { name: 'Height', type: 'float', default: 0.5 },
1220
- { name: 'Radius', type: 'float', default: 0.1 },
1221
- ],
1222
- outputs: [{ name: 'Out', type: 'float' }],
1223
- glsl: `
1224
- vec2 d = abs({{input.UV}} - 0.5) - vec2({{input.Width}}, {{input.Height}}) * 0.5 + {{input.Radius}};
1225
- float {{output.Out}} = 1.0 - smoothstep(0.0, 0.01, length(max(d, 0.0)) - {{input.Radius}});
1226
- `,
1227
- },
1228
- {
1229
- id: 'polygon',
1230
- name: 'Polygon',
1231
- category: 'procedural',
1232
- inputs: [
1233
- { name: 'UV', type: 'vec2', default: [0, 0] },
1234
- { name: 'Sides', type: 'float', default: 6 },
1235
- { name: 'Width', type: 'float', default: 0.5 },
1236
- { name: 'Height', type: 'float', default: 0.5 },
1237
- ],
1238
- outputs: [{ name: 'Out', type: 'float' }],
1239
- glsl: `
1240
- vec2 d = {{input.UV}} - 0.5;
1241
- float angle = atan(d.y, d.x);
1242
- float slice = 6.283185 / {{input.Sides}};
1243
- float dist = cos(floor(0.5 + angle / slice) * slice - angle) * length(d * 2.0 / vec2({{input.Width}}, {{input.Height}}));
1244
- float {{output.Out}} = 1.0 - smoothstep(1.0, 1.01, dist);
1245
- `,
1246
- },
1247
- // ─── Output Nodes ────────────────────────────────────────
1248
- {
1249
- id: 'pbrMasterNode',
1250
- name: 'PBR Master',
1251
- category: 'output',
1252
- description: 'Physically Based Rendering output',
1253
- isMaster: true,
1254
- inputs: [
1255
- { name: 'Albedo', type: 'vec3', default: [1, 1, 1] },
1256
- { name: 'Normal', type: 'vec3', default: [0, 0, 1] },
1257
- { name: 'Metallic', type: 'float', default: 0 },
1258
- { name: 'Smoothness', type: 'float', default: 0.5 },
1259
- { name: 'AO', type: 'float', default: 1 },
1260
- { name: 'Emission', type: 'vec3', default: [0, 0, 0] },
1261
- { name: 'Alpha', type: 'float', default: 1 },
1262
- { name: 'AlphaClip', type: 'float', default: 0 },
1263
- ],
1264
- outputs: [],
1265
- glsl: `
1266
- // PBR output
1267
- gl_FragColor = vec4({{input.Albedo}}, {{input.Alpha}});
1268
-
1269
- // Normal output
1270
- normalOutput = {{input.Normal}};
1271
-
1272
- // Material properties
1273
- metallicOutput = {{input.Metallic}};
1274
- smoothnessOutput = {{input.Smoothness}};
1275
- aoOutput = {{input.AO}};
1276
- emissionOutput = {{input.Emission}};
1277
-
1278
- // Alpha clip
1279
- if ({{input.Alpha}} < {{input.AlphaClip}}) discard;
1280
- `,
1281
- },
1282
- {
1283
- id: 'unlitMasterNode',
1284
- name: 'Unlit Master',
1285
- category: 'output',
1286
- description: 'Unlit/emissive output',
1287
- isMaster: true,
1288
- inputs: [
1289
- { name: 'Color', type: 'vec3', default: [1, 1, 1] },
1290
- { name: 'Alpha', type: 'float', default: 1 },
1291
- { name: 'AlphaClip', type: 'float', default: 0 },
1292
- ],
1293
- outputs: [],
1294
- glsl: `
1295
- gl_FragColor = vec4({{input.Color}}, {{input.Alpha}});
1296
- if ({{input.Alpha}} < {{input.AlphaClip}}) discard;
1297
- `,
1298
- },
1299
- {
1300
- id: 'vertexMasterNode',
1301
- name: 'Vertex Master',
1302
- category: 'output',
1303
- description: 'Vertex shader output',
1304
- isMaster: true,
1305
- stage: 'vertex',
1306
- inputs: [
1307
- { name: 'Position', type: 'vec3' },
1308
- { name: 'Normal', type: 'vec3' },
1309
- { name: 'Tangent', type: 'vec3' },
1310
- ],
1311
- outputs: [],
1312
- glsl: `
1313
- gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * vec4({{input.Position}}, 1.0);
1314
- `,
1315
- },
2
+ // ─── Input Nodes ─────────────────────────────────────────
3
+ {
4
+ id: "position",
5
+ name: "Position",
6
+ category: "input",
7
+ description: "World/Object/View position",
8
+ inputs: [],
9
+ outputs: [
10
+ { name: "World", type: "vec3" },
11
+ { name: "Object", type: "vec3" },
12
+ { name: "View", type: "vec3" },
13
+ { name: "Tangent", type: "vec3" }
14
+ ],
15
+ glsl: `
16
+ vec3 {{output.World}} = v_worldPosition;
17
+ vec3 {{output.Object}} = v_objectPosition;
18
+ vec3 {{output.View}} = v_viewPosition;
19
+ vec3 {{output.Tangent}} = v_tangent;
20
+ `
21
+ },
22
+ {
23
+ id: "normal",
24
+ name: "Normal",
25
+ category: "input",
26
+ description: "Surface normal vectors",
27
+ inputs: [],
28
+ outputs: [
29
+ { name: "World", type: "vec3" },
30
+ { name: "Object", type: "vec3" },
31
+ { name: "View", type: "vec3" },
32
+ { name: "Tangent", type: "vec3" }
33
+ ],
34
+ glsl: `
35
+ vec3 {{output.World}} = normalize(v_worldNormal);
36
+ vec3 {{output.Object}} = normalize(v_objectNormal);
37
+ vec3 {{output.View}} = normalize(v_viewNormal);
38
+ vec3 {{output.Tangent}} = normalize(v_tangentNormal);
39
+ `
40
+ },
41
+ {
42
+ id: "uv",
43
+ name: "UV",
44
+ category: "input",
45
+ description: "Texture coordinates",
46
+ inputs: [],
47
+ outputs: [
48
+ { name: "UV0", type: "vec2" },
49
+ { name: "UV1", type: "vec2" },
50
+ { name: "UV2", type: "vec2" },
51
+ { name: "UV3", type: "vec2" }
52
+ ],
53
+ glsl: `
54
+ vec2 {{output.UV0}} = v_uv0;
55
+ vec2 {{output.UV1}} = v_uv1;
56
+ vec2 {{output.UV2}} = v_uv2;
57
+ vec2 {{output.UV3}} = v_uv3;
58
+ `
59
+ },
60
+ {
61
+ id: "vertexColor",
62
+ name: "Vertex Color",
63
+ category: "input",
64
+ description: "Per-vertex color",
65
+ inputs: [],
66
+ outputs: [
67
+ { name: "Color", type: "vec4" },
68
+ { name: "R", type: "float" },
69
+ { name: "G", type: "float" },
70
+ { name: "B", type: "float" },
71
+ { name: "A", type: "float" }
72
+ ],
73
+ glsl: `
74
+ vec4 {{output.Color}} = v_color;
75
+ float {{output.R}} = v_color.r;
76
+ float {{output.G}} = v_color.g;
77
+ float {{output.B}} = v_color.b;
78
+ float {{output.A}} = v_color.a;
79
+ `
80
+ },
81
+ {
82
+ id: "time",
83
+ name: "Time",
84
+ category: "input",
85
+ description: "Time values for animation",
86
+ inputs: [],
87
+ outputs: [
88
+ { name: "Time", type: "float" },
89
+ { name: "SinTime", type: "float" },
90
+ { name: "CosTime", type: "float" },
91
+ { name: "DeltaTime", type: "float" },
92
+ { name: "SmoothDelta", type: "float" }
93
+ ],
94
+ glsl: `
95
+ float {{output.Time}} = u_time;
96
+ float {{output.SinTime}} = sin(u_time);
97
+ float {{output.CosTime}} = cos(u_time);
98
+ float {{output.DeltaTime}} = u_deltaTime;
99
+ float {{output.SmoothDelta}} = u_smoothDeltaTime;
100
+ `
101
+ },
102
+ {
103
+ id: "viewDirection",
104
+ name: "View Direction",
105
+ category: "input",
106
+ description: "Camera view direction",
107
+ inputs: [],
108
+ outputs: [
109
+ { name: "World", type: "vec3" },
110
+ { name: "Object", type: "vec3" },
111
+ { name: "View", type: "vec3" }
112
+ ],
113
+ glsl: `
114
+ vec3 {{output.World}} = normalize(u_cameraPosition - v_worldPosition);
115
+ vec3 {{output.Object}} = (u_worldToObject * vec4({{output.World}}, 0.0)).xyz;
116
+ vec3 {{output.View}} = (u_viewMatrix * vec4({{output.World}}, 0.0)).xyz;
117
+ `
118
+ },
119
+ {
120
+ id: "cameraPosition",
121
+ name: "Camera Position",
122
+ category: "input",
123
+ inputs: [],
124
+ outputs: [{ name: "Position", type: "vec3" }],
125
+ glsl: `vec3 {{output.Position}} = u_cameraPosition;`
126
+ },
127
+ {
128
+ id: "screenPosition",
129
+ name: "Screen Position",
130
+ category: "input",
131
+ inputs: [],
132
+ outputs: [
133
+ { name: "Default", type: "vec4" },
134
+ { name: "Raw", type: "vec4" },
135
+ { name: "Center", type: "vec2" },
136
+ { name: "Tiled", type: "vec2" }
137
+ ],
138
+ glsl: `
139
+ vec4 {{output.Default}} = gl_FragCoord;
140
+ vec4 {{output.Raw}} = gl_FragCoord;
141
+ vec2 {{output.Center}} = gl_FragCoord.xy / u_resolution - 0.5;
142
+ vec2 {{output.Tiled}} = fract(gl_FragCoord.xy / 256.0);
143
+ `
144
+ },
145
+ {
146
+ id: "constant",
147
+ name: "Constant",
148
+ category: "input",
149
+ description: "Constant value",
150
+ inputs: [],
151
+ outputs: [{ name: "Out", type: "float" }],
152
+ properties: [{ name: "Value", type: "float", default: 0 }],
153
+ glsl: `float {{output.Out}} = {{prop.Value}};`
154
+ },
155
+ {
156
+ id: "color",
157
+ name: "Color",
158
+ category: "input",
159
+ description: "Color constant",
160
+ inputs: [],
161
+ outputs: [
162
+ { name: "Out", type: "vec4" },
163
+ { name: "RGB", type: "vec3" },
164
+ { name: "R", type: "float" },
165
+ { name: "G", type: "float" },
166
+ { name: "B", type: "float" },
167
+ { name: "A", type: "float" }
168
+ ],
169
+ properties: [{ name: "Color", type: "color", default: [1, 1, 1, 1] }],
170
+ glsl: `
171
+ vec4 {{output.Out}} = vec4({{prop.Color}});
172
+ vec3 {{output.RGB}} = {{output.Out}}.rgb;
173
+ float {{output.R}} = {{output.Out}}.r;
174
+ float {{output.G}} = {{output.Out}}.g;
175
+ float {{output.B}} = {{output.Out}}.b;
176
+ float {{output.A}} = {{output.Out}}.a;
177
+ `
178
+ },
179
+ {
180
+ id: "vector2",
181
+ name: "Vector 2",
182
+ category: "input",
183
+ inputs: [],
184
+ outputs: [{ name: "Out", type: "vec2" }],
185
+ properties: [{ name: "Value", type: "vec2", default: [0, 0] }],
186
+ glsl: `vec2 {{output.Out}} = vec2({{prop.Value}});`
187
+ },
188
+ {
189
+ id: "vector3",
190
+ name: "Vector 3",
191
+ category: "input",
192
+ inputs: [],
193
+ outputs: [{ name: "Out", type: "vec3" }],
194
+ properties: [{ name: "Value", type: "vec3", default: [0, 0, 0] }],
195
+ glsl: `vec3 {{output.Out}} = vec3({{prop.Value}});`
196
+ },
197
+ {
198
+ id: "vector4",
199
+ name: "Vector 4",
200
+ category: "input",
201
+ inputs: [],
202
+ outputs: [{ name: "Out", type: "vec4" }],
203
+ properties: [{ name: "Value", type: "vec4", default: [0, 0, 0, 0] }],
204
+ glsl: `vec4 {{output.Out}} = vec4({{prop.Value}});`
205
+ },
206
+ // ─── Math Nodes ──────────────────────────────────────────
207
+ {
208
+ id: "add",
209
+ name: "Add",
210
+ category: "math",
211
+ inputs: [
212
+ { name: "A", type: "float", default: 0 },
213
+ { name: "B", type: "float", default: 0 }
214
+ ],
215
+ outputs: [{ name: "Out", type: "float" }],
216
+ glsl: `float {{output.Out}} = {{input.A}} + {{input.B}};`
217
+ },
218
+ {
219
+ id: "subtract",
220
+ name: "Subtract",
221
+ category: "math",
222
+ inputs: [
223
+ { name: "A", type: "float", default: 0 },
224
+ { name: "B", type: "float", default: 0 }
225
+ ],
226
+ outputs: [{ name: "Out", type: "float" }],
227
+ glsl: `float {{output.Out}} = {{input.A}} - {{input.B}};`
228
+ },
229
+ {
230
+ id: "multiply",
231
+ name: "Multiply",
232
+ category: "math",
233
+ inputs: [
234
+ { name: "A", type: "float", default: 1 },
235
+ { name: "B", type: "float", default: 1 }
236
+ ],
237
+ outputs: [{ name: "Out", type: "float" }],
238
+ glsl: `float {{output.Out}} = {{input.A}} * {{input.B}};`
239
+ },
240
+ {
241
+ id: "divide",
242
+ name: "Divide",
243
+ category: "math",
244
+ inputs: [
245
+ { name: "A", type: "float", default: 1 },
246
+ { name: "B", type: "float", default: 1 }
247
+ ],
248
+ outputs: [{ name: "Out", type: "float" }],
249
+ glsl: `float {{output.Out}} = {{input.A}} / max({{input.B}}, 0.0001);`
250
+ },
251
+ {
252
+ id: "power",
253
+ name: "Power",
254
+ category: "math",
255
+ inputs: [
256
+ { name: "Base", type: "float", default: 2 },
257
+ { name: "Exp", type: "float", default: 2 }
258
+ ],
259
+ outputs: [{ name: "Out", type: "float" }],
260
+ glsl: `float {{output.Out}} = pow({{input.Base}}, {{input.Exp}});`
261
+ },
262
+ {
263
+ id: "sqrt",
264
+ name: "Square Root",
265
+ category: "math",
266
+ inputs: [{ name: "In", type: "float", default: 1 }],
267
+ outputs: [{ name: "Out", type: "float" }],
268
+ glsl: `float {{output.Out}} = sqrt(max({{input.In}}, 0.0));`
269
+ },
270
+ {
271
+ id: "abs",
272
+ name: "Absolute",
273
+ category: "math",
274
+ inputs: [{ name: "In", type: "float", default: 0 }],
275
+ outputs: [{ name: "Out", type: "float" }],
276
+ glsl: `float {{output.Out}} = abs({{input.In}});`
277
+ },
278
+ {
279
+ id: "negate",
280
+ name: "Negate",
281
+ category: "math",
282
+ inputs: [{ name: "In", type: "float", default: 0 }],
283
+ outputs: [{ name: "Out", type: "float" }],
284
+ glsl: `float {{output.Out}} = -{{input.In}};`
285
+ },
286
+ {
287
+ id: "min",
288
+ name: "Minimum",
289
+ category: "math",
290
+ inputs: [
291
+ { name: "A", type: "float", default: 0 },
292
+ { name: "B", type: "float", default: 0 }
293
+ ],
294
+ outputs: [{ name: "Out", type: "float" }],
295
+ glsl: `float {{output.Out}} = min({{input.A}}, {{input.B}});`
296
+ },
297
+ {
298
+ id: "max",
299
+ name: "Maximum",
300
+ category: "math",
301
+ inputs: [
302
+ { name: "A", type: "float", default: 0 },
303
+ { name: "B", type: "float", default: 0 }
304
+ ],
305
+ outputs: [{ name: "Out", type: "float" }],
306
+ glsl: `float {{output.Out}} = max({{input.A}}, {{input.B}});`
307
+ },
308
+ {
309
+ id: "clamp",
310
+ name: "Clamp",
311
+ category: "math",
312
+ inputs: [
313
+ { name: "In", type: "float", default: 0 },
314
+ { name: "Min", type: "float", default: 0 },
315
+ { name: "Max", type: "float", default: 1 }
316
+ ],
317
+ outputs: [{ name: "Out", type: "float" }],
318
+ glsl: `float {{output.Out}} = clamp({{input.In}}, {{input.Min}}, {{input.Max}});`
319
+ },
320
+ {
321
+ id: "saturate",
322
+ name: "Saturate",
323
+ category: "math",
324
+ description: "Clamp to 0-1 range",
325
+ inputs: [{ name: "In", type: "float", default: 0 }],
326
+ outputs: [{ name: "Out", type: "float" }],
327
+ glsl: `float {{output.Out}} = clamp({{input.In}}, 0.0, 1.0);`
328
+ },
329
+ {
330
+ id: "lerp",
331
+ name: "Lerp",
332
+ category: "math",
333
+ description: "Linear interpolation",
334
+ inputs: [
335
+ { name: "A", type: "float", default: 0 },
336
+ { name: "B", type: "float", default: 1 },
337
+ { name: "T", type: "float", default: 0.5 }
338
+ ],
339
+ outputs: [{ name: "Out", type: "float" }],
340
+ glsl: `float {{output.Out}} = mix({{input.A}}, {{input.B}}, {{input.T}});`
341
+ },
342
+ {
343
+ id: "smoothstep",
344
+ name: "Smoothstep",
345
+ category: "math",
346
+ inputs: [
347
+ { name: "Edge0", type: "float", default: 0 },
348
+ { name: "Edge1", type: "float", default: 1 },
349
+ { name: "In", type: "float", default: 0.5 }
350
+ ],
351
+ outputs: [{ name: "Out", type: "float" }],
352
+ glsl: `float {{output.Out}} = smoothstep({{input.Edge0}}, {{input.Edge1}}, {{input.In}});`
353
+ },
354
+ {
355
+ id: "step",
356
+ name: "Step",
357
+ category: "math",
358
+ inputs: [
359
+ { name: "Edge", type: "float", default: 0.5 },
360
+ { name: "In", type: "float", default: 0 }
361
+ ],
362
+ outputs: [{ name: "Out", type: "float" }],
363
+ glsl: `float {{output.Out}} = step({{input.Edge}}, {{input.In}});`
364
+ },
365
+ {
366
+ id: "floor",
367
+ name: "Floor",
368
+ category: "math",
369
+ inputs: [{ name: "In", type: "float", default: 0 }],
370
+ outputs: [{ name: "Out", type: "float" }],
371
+ glsl: `float {{output.Out}} = floor({{input.In}});`
372
+ },
373
+ {
374
+ id: "ceil",
375
+ name: "Ceiling",
376
+ category: "math",
377
+ inputs: [{ name: "In", type: "float", default: 0 }],
378
+ outputs: [{ name: "Out", type: "float" }],
379
+ glsl: `float {{output.Out}} = ceil({{input.In}});`
380
+ },
381
+ {
382
+ id: "round",
383
+ name: "Round",
384
+ category: "math",
385
+ inputs: [{ name: "In", type: "float", default: 0 }],
386
+ outputs: [{ name: "Out", type: "float" }],
387
+ glsl: `float {{output.Out}} = floor({{input.In}} + 0.5);`
388
+ },
389
+ {
390
+ id: "frac",
391
+ name: "Fraction",
392
+ category: "math",
393
+ inputs: [{ name: "In", type: "float", default: 0 }],
394
+ outputs: [{ name: "Out", type: "float" }],
395
+ glsl: `float {{output.Out}} = fract({{input.In}});`
396
+ },
397
+ {
398
+ id: "mod",
399
+ name: "Modulo",
400
+ category: "math",
401
+ inputs: [
402
+ { name: "A", type: "float", default: 0 },
403
+ { name: "B", type: "float", default: 1 }
404
+ ],
405
+ outputs: [{ name: "Out", type: "float" }],
406
+ glsl: `float {{output.Out}} = mod({{input.A}}, {{input.B}});`
407
+ },
408
+ {
409
+ id: "sin",
410
+ name: "Sine",
411
+ category: "math",
412
+ inputs: [{ name: "In", type: "float", default: 0 }],
413
+ outputs: [{ name: "Out", type: "float" }],
414
+ glsl: `float {{output.Out}} = sin({{input.In}});`
415
+ },
416
+ {
417
+ id: "cos",
418
+ name: "Cosine",
419
+ category: "math",
420
+ inputs: [{ name: "In", type: "float", default: 0 }],
421
+ outputs: [{ name: "Out", type: "float" }],
422
+ glsl: `float {{output.Out}} = cos({{input.In}});`
423
+ },
424
+ {
425
+ id: "tan",
426
+ name: "Tangent",
427
+ category: "math",
428
+ inputs: [{ name: "In", type: "float", default: 0 }],
429
+ outputs: [{ name: "Out", type: "float" }],
430
+ glsl: `float {{output.Out}} = tan({{input.In}});`
431
+ },
432
+ {
433
+ id: "asin",
434
+ name: "Arcsine",
435
+ category: "math",
436
+ inputs: [{ name: "In", type: "float", default: 0 }],
437
+ outputs: [{ name: "Out", type: "float" }],
438
+ glsl: `float {{output.Out}} = asin(clamp({{input.In}}, -1.0, 1.0));`
439
+ },
440
+ {
441
+ id: "acos",
442
+ name: "Arccosine",
443
+ category: "math",
444
+ inputs: [{ name: "In", type: "float", default: 0 }],
445
+ outputs: [{ name: "Out", type: "float" }],
446
+ glsl: `float {{output.Out}} = acos(clamp({{input.In}}, -1.0, 1.0));`
447
+ },
448
+ {
449
+ id: "atan",
450
+ name: "Arctangent",
451
+ category: "math",
452
+ inputs: [{ name: "In", type: "float", default: 0 }],
453
+ outputs: [{ name: "Out", type: "float" }],
454
+ glsl: `float {{output.Out}} = atan({{input.In}});`
455
+ },
456
+ {
457
+ id: "atan2",
458
+ name: "Arctangent2",
459
+ category: "math",
460
+ inputs: [
461
+ { name: "Y", type: "float", default: 0 },
462
+ { name: "X", type: "float", default: 1 }
463
+ ],
464
+ outputs: [{ name: "Out", type: "float" }],
465
+ glsl: `float {{output.Out}} = atan({{input.Y}}, {{input.X}});`
466
+ },
467
+ {
468
+ id: "exp",
469
+ name: "Exponential",
470
+ category: "math",
471
+ inputs: [{ name: "In", type: "float", default: 0 }],
472
+ outputs: [{ name: "Out", type: "float" }],
473
+ glsl: `float {{output.Out}} = exp({{input.In}});`
474
+ },
475
+ {
476
+ id: "exp2",
477
+ name: "Exponential 2",
478
+ category: "math",
479
+ inputs: [{ name: "In", type: "float", default: 0 }],
480
+ outputs: [{ name: "Out", type: "float" }],
481
+ glsl: `float {{output.Out}} = exp2({{input.In}});`
482
+ },
483
+ {
484
+ id: "log",
485
+ name: "Logarithm",
486
+ category: "math",
487
+ inputs: [{ name: "In", type: "float", default: 1 }],
488
+ outputs: [{ name: "Out", type: "float" }],
489
+ glsl: `float {{output.Out}} = log(max({{input.In}}, 0.0001));`
490
+ },
491
+ {
492
+ id: "log2",
493
+ name: "Logarithm 2",
494
+ category: "math",
495
+ inputs: [{ name: "In", type: "float", default: 1 }],
496
+ outputs: [{ name: "Out", type: "float" }],
497
+ glsl: `float {{output.Out}} = log2(max({{input.In}}, 0.0001));`
498
+ },
499
+ {
500
+ id: "oneMinus",
501
+ name: "One Minus",
502
+ category: "math",
503
+ inputs: [{ name: "In", type: "float", default: 0 }],
504
+ outputs: [{ name: "Out", type: "float" }],
505
+ glsl: `float {{output.Out}} = 1.0 - {{input.In}};`
506
+ },
507
+ {
508
+ id: "remap",
509
+ name: "Remap",
510
+ category: "math",
511
+ description: "Remap value from one range to another",
512
+ inputs: [
513
+ { name: "In", type: "float", default: 0 },
514
+ { name: "InMin", type: "float", default: 0 },
515
+ { name: "InMax", type: "float", default: 1 },
516
+ { name: "OutMin", type: "float", default: 0 },
517
+ { name: "OutMax", type: "float", default: 1 }
518
+ ],
519
+ outputs: [{ name: "Out", type: "float" }],
520
+ glsl: `
521
+ float {{output.Out}} = {{input.OutMin}} + ({{input.In}} - {{input.InMin}}) * ({{input.OutMax}} - {{input.OutMin}}) / ({{input.InMax}} - {{input.InMin}});
522
+ `
523
+ },
524
+ // ─── Vector Nodes ────────────────────────────────────────
525
+ {
526
+ id: "vectorSplit",
527
+ name: "Split",
528
+ category: "vector",
529
+ description: "Split vector into components",
530
+ inputs: [{ name: "In", type: "vec4", default: [0, 0, 0, 0] }],
531
+ outputs: [
532
+ { name: "X", type: "float" },
533
+ { name: "Y", type: "float" },
534
+ { name: "Z", type: "float" },
535
+ { name: "W", type: "float" }
536
+ ],
537
+ glsl: `
538
+ float {{output.X}} = {{input.In}}.x;
539
+ float {{output.Y}} = {{input.In}}.y;
540
+ float {{output.Z}} = {{input.In}}.z;
541
+ float {{output.W}} = {{input.In}}.w;
542
+ `
543
+ },
544
+ {
545
+ id: "vectorCombine",
546
+ name: "Combine",
547
+ category: "vector",
548
+ description: "Combine components into vector",
549
+ inputs: [
550
+ { name: "X", type: "float", default: 0 },
551
+ { name: "Y", type: "float", default: 0 },
552
+ { name: "Z", type: "float", default: 0 },
553
+ { name: "W", type: "float", default: 0 }
554
+ ],
555
+ outputs: [
556
+ { name: "XYZW", type: "vec4" },
557
+ { name: "XYZ", type: "vec3" },
558
+ { name: "XY", type: "vec2" }
559
+ ],
560
+ glsl: `
561
+ vec4 {{output.XYZW}} = vec4({{input.X}}, {{input.Y}}, {{input.Z}}, {{input.W}});
562
+ vec3 {{output.XYZ}} = vec3({{input.X}}, {{input.Y}}, {{input.Z}});
563
+ vec2 {{output.XY}} = vec2({{input.X}}, {{input.Y}});
564
+ `
565
+ },
566
+ {
567
+ id: "dot",
568
+ name: "Dot Product",
569
+ category: "vector",
570
+ inputs: [
571
+ { name: "A", type: "vec3", default: [1, 0, 0] },
572
+ { name: "B", type: "vec3", default: [0, 1, 0] }
573
+ ],
574
+ outputs: [{ name: "Out", type: "float" }],
575
+ glsl: `float {{output.Out}} = dot({{input.A}}, {{input.B}});`
576
+ },
577
+ {
578
+ id: "cross",
579
+ name: "Cross Product",
580
+ category: "vector",
581
+ inputs: [
582
+ { name: "A", type: "vec3", default: [1, 0, 0] },
583
+ { name: "B", type: "vec3", default: [0, 1, 0] }
584
+ ],
585
+ outputs: [{ name: "Out", type: "vec3" }],
586
+ glsl: `vec3 {{output.Out}} = cross({{input.A}}, {{input.B}});`
587
+ },
588
+ {
589
+ id: "normalize",
590
+ name: "Normalize",
591
+ category: "vector",
592
+ inputs: [{ name: "In", type: "vec3", default: [1, 0, 0] }],
593
+ outputs: [{ name: "Out", type: "vec3" }],
594
+ glsl: `vec3 {{output.Out}} = normalize({{input.In}});`
595
+ },
596
+ {
597
+ id: "length",
598
+ name: "Length",
599
+ category: "vector",
600
+ inputs: [{ name: "In", type: "vec3", default: [1, 0, 0] }],
601
+ outputs: [{ name: "Out", type: "float" }],
602
+ glsl: `float {{output.Out}} = length({{input.In}});`
603
+ },
604
+ {
605
+ id: "distance",
606
+ name: "Distance",
607
+ category: "vector",
608
+ inputs: [
609
+ { name: "A", type: "vec3", default: [0, 0, 0] },
610
+ { name: "B", type: "vec3", default: [1, 0, 0] }
611
+ ],
612
+ outputs: [{ name: "Out", type: "float" }],
613
+ glsl: `float {{output.Out}} = distance({{input.A}}, {{input.B}});`
614
+ },
615
+ {
616
+ id: "reflect",
617
+ name: "Reflect",
618
+ category: "vector",
619
+ inputs: [
620
+ { name: "In", type: "vec3", default: [1, 0, 0] },
621
+ { name: "Normal", type: "vec3", default: [0, 1, 0] }
622
+ ],
623
+ outputs: [{ name: "Out", type: "vec3" }],
624
+ glsl: `vec3 {{output.Out}} = reflect({{input.In}}, {{input.Normal}});`
625
+ },
626
+ {
627
+ id: "refract",
628
+ name: "Refract",
629
+ category: "vector",
630
+ inputs: [
631
+ { name: "In", type: "vec3", default: [1, 0, 0] },
632
+ { name: "Normal", type: "vec3", default: [0, 1, 0] },
633
+ { name: "IOR", type: "float", default: 1.5 }
634
+ ],
635
+ outputs: [{ name: "Out", type: "vec3" }],
636
+ glsl: `vec3 {{output.Out}} = refract({{input.In}}, {{input.Normal}}, 1.0 / {{input.IOR}});`
637
+ },
638
+ // ─── Texture Nodes ───────────────────────────────────────
639
+ {
640
+ id: "sampleTexture2D",
641
+ name: "Sample Texture 2D",
642
+ category: "texture",
643
+ inputs: [{ name: "UV", type: "vec2", default: [0, 0] }],
644
+ outputs: [
645
+ { name: "RGBA", type: "vec4" },
646
+ { name: "RGB", type: "vec3" },
647
+ { name: "R", type: "float" },
648
+ { name: "G", type: "float" },
649
+ { name: "B", type: "float" },
650
+ { name: "A", type: "float" }
651
+ ],
652
+ properties: [{ name: "Texture", type: "texture", default: null }],
653
+ glsl: `
654
+ vec4 {{output.RGBA}} = texture({{prop.Texture}}, {{input.UV}});
655
+ vec3 {{output.RGB}} = {{output.RGBA}}.rgb;
656
+ float {{output.R}} = {{output.RGBA}}.r;
657
+ float {{output.G}} = {{output.RGBA}}.g;
658
+ float {{output.B}} = {{output.RGBA}}.b;
659
+ float {{output.A}} = {{output.RGBA}}.a;
660
+ `
661
+ },
662
+ {
663
+ id: "sampleNormalMap",
664
+ name: "Sample Normal Map",
665
+ category: "texture",
666
+ inputs: [
667
+ { name: "UV", type: "vec2", default: [0, 0] },
668
+ { name: "Strength", type: "float", default: 1 }
669
+ ],
670
+ outputs: [{ name: "Normal", type: "vec3" }],
671
+ properties: [{ name: "Texture", type: "texture", default: null }],
672
+ glsl: `
673
+ vec3 normalSample = texture({{prop.Texture}}, {{input.UV}}).rgb * 2.0 - 1.0;
674
+ normalSample.xy *= {{input.Strength}};
675
+ vec3 {{output.Normal}} = normalize(normalSample);
676
+ `
677
+ },
678
+ {
679
+ id: "sampleCubemap",
680
+ name: "Sample Cubemap",
681
+ category: "texture",
682
+ inputs: [{ name: "Direction", type: "vec3", default: [0, 1, 0] }],
683
+ outputs: [{ name: "RGBA", type: "vec4" }],
684
+ properties: [{ name: "Cubemap", type: "texture", default: null }],
685
+ glsl: `vec4 {{output.RGBA}} = textureCube({{prop.Cubemap}}, {{input.Direction}});`
686
+ },
687
+ {
688
+ id: "triplanar",
689
+ name: "Triplanar Mapping",
690
+ category: "texture",
691
+ description: "Sample texture using world position and normal",
692
+ inputs: [
693
+ { name: "Position", type: "vec3" },
694
+ { name: "Normal", type: "vec3" },
695
+ { name: "Tile", type: "float", default: 1 },
696
+ { name: "Blend", type: "float", default: 1 }
697
+ ],
698
+ outputs: [{ name: "RGBA", type: "vec4" }],
699
+ properties: [{ name: "Texture", type: "texture", default: null }],
700
+ glsl: `
701
+ vec3 blending = pow(abs({{input.Normal}}), vec3({{input.Blend}}));
702
+ blending /= dot(blending, vec3(1.0));
703
+
704
+ vec4 xProject = texture({{prop.Texture}}, {{input.Position}}.yz * {{input.Tile}});
705
+ vec4 yProject = texture({{prop.Texture}}, {{input.Position}}.xz * {{input.Tile}});
706
+ vec4 zProject = texture({{prop.Texture}}, {{input.Position}}.xy * {{input.Tile}});
707
+
708
+ vec4 {{output.RGBA}} = xProject * blending.x + yProject * blending.y + zProject * blending.z;
709
+ `
710
+ },
711
+ // ─── UV Nodes ────────────────────────────────────────────
712
+ {
713
+ id: "tiling",
714
+ name: "Tiling and Offset",
715
+ category: "uv",
716
+ inputs: [
717
+ { name: "UV", type: "vec2", default: [0, 0] },
718
+ { name: "Tiling", type: "vec2", default: [1, 1] },
719
+ { name: "Offset", type: "vec2", default: [0, 0] }
720
+ ],
721
+ outputs: [{ name: "Out", type: "vec2" }],
722
+ glsl: `vec2 {{output.Out}} = {{input.UV}} * {{input.Tiling}} + {{input.Offset}};`
723
+ },
724
+ {
725
+ id: "rotate",
726
+ name: "Rotate",
727
+ category: "uv",
728
+ inputs: [
729
+ { name: "UV", type: "vec2", default: [0, 0] },
730
+ { name: "Center", type: "vec2", default: [0.5, 0.5] },
731
+ { name: "Rotation", type: "float", default: 0 }
732
+ ],
733
+ outputs: [{ name: "Out", type: "vec2" }],
734
+ glsl: `
735
+ vec2 uvCentered = {{input.UV}} - {{input.Center}};
736
+ float c = cos({{input.Rotation}});
737
+ float s = sin({{input.Rotation}});
738
+ vec2 {{output.Out}} = vec2(uvCentered.x * c - uvCentered.y * s, uvCentered.x * s + uvCentered.y * c) + {{input.Center}};
739
+ `
740
+ },
741
+ {
742
+ id: "flipbook",
743
+ name: "Flipbook",
744
+ category: "uv",
745
+ description: "Animated sprite sheet UV",
746
+ inputs: [
747
+ { name: "UV", type: "vec2", default: [0, 0] },
748
+ { name: "Width", type: "float", default: 4 },
749
+ { name: "Height", type: "float", default: 4 },
750
+ { name: "Tile", type: "float", default: 0 }
751
+ ],
752
+ outputs: [{ name: "Out", type: "vec2" }],
753
+ glsl: `
754
+ float tile = floor({{input.Tile}});
755
+ float invWidth = 1.0 / {{input.Width}};
756
+ float invHeight = 1.0 / {{input.Height}};
757
+ float tileX = mod(tile, {{input.Width}});
758
+ float tileY = floor(tile * invWidth);
759
+ vec2 {{output.Out}} = ({{input.UV}} + vec2(tileX, tileY)) * vec2(invWidth, invHeight);
760
+ `
761
+ },
762
+ {
763
+ id: "polar",
764
+ name: "Polar Coordinates",
765
+ category: "uv",
766
+ inputs: [
767
+ { name: "UV", type: "vec2", default: [0, 0] },
768
+ { name: "Center", type: "vec2", default: [0.5, 0.5] },
769
+ { name: "RadialScale", type: "float", default: 1 },
770
+ { name: "LengthScale", type: "float", default: 1 }
771
+ ],
772
+ outputs: [{ name: "Out", type: "vec2" }],
773
+ glsl: `
774
+ vec2 delta = {{input.UV}} - {{input.Center}};
775
+ float radius = length(delta) * 2.0 * {{input.LengthScale}};
776
+ float angle = atan(delta.y, delta.x) / 6.283185 + 0.5;
777
+ vec2 {{output.Out}} = vec2(radius, angle * {{input.RadialScale}});
778
+ `
779
+ },
780
+ {
781
+ id: "spherize",
782
+ name: "Spherize",
783
+ category: "uv",
784
+ inputs: [
785
+ { name: "UV", type: "vec2", default: [0, 0] },
786
+ { name: "Center", type: "vec2", default: [0.5, 0.5] },
787
+ { name: "Strength", type: "float", default: 0.5 },
788
+ { name: "Offset", type: "vec2", default: [0, 0] }
789
+ ],
790
+ outputs: [{ name: "Out", type: "vec2" }],
791
+ glsl: `
792
+ vec2 delta = {{input.UV}} - {{input.Center}};
793
+ float dist = length(delta);
794
+ float factor = 1.0 + dist * dist * {{input.Strength}};
795
+ vec2 {{output.Out}} = {{input.Center}} + delta / factor + {{input.Offset}};
796
+ `
797
+ },
798
+ {
799
+ id: "twirl",
800
+ name: "Twirl",
801
+ category: "uv",
802
+ inputs: [
803
+ { name: "UV", type: "vec2", default: [0, 0] },
804
+ { name: "Center", type: "vec2", default: [0.5, 0.5] },
805
+ { name: "Strength", type: "float", default: 1 },
806
+ { name: "Offset", type: "vec2", default: [0, 0] }
807
+ ],
808
+ outputs: [{ name: "Out", type: "vec2" }],
809
+ glsl: `
810
+ vec2 delta = {{input.UV}} - {{input.Center}};
811
+ float dist = length(delta);
812
+ float angle = {{input.Strength}} * dist;
813
+ float c = cos(angle);
814
+ float s = sin(angle);
815
+ vec2 {{output.Out}} = vec2(delta.x * c - delta.y * s, delta.x * s + delta.y * c) + {{input.Center}} + {{input.Offset}};
816
+ `
817
+ },
818
+ {
819
+ id: "parallax",
820
+ name: "Parallax Mapping",
821
+ category: "uv",
822
+ inputs: [
823
+ { name: "UV", type: "vec2", default: [0, 0] },
824
+ { name: "Height", type: "float", default: 0.5 },
825
+ { name: "ViewDir", type: "vec3" },
826
+ { name: "Amplitude", type: "float", default: 0.05 }
827
+ ],
828
+ outputs: [{ name: "Out", type: "vec2" }],
829
+ glsl: `
830
+ float h = {{input.Height}};
831
+ vec2 {{output.Out}} = {{input.UV}} - {{input.ViewDir}}.xy * (h * {{input.Amplitude}});
832
+ `
833
+ },
834
+ // ─── Color Nodes ─────────────────────────────────────────
835
+ {
836
+ id: "blend",
837
+ name: "Blend",
838
+ category: "color",
839
+ description: "Blend two colors",
840
+ inputs: [
841
+ { name: "Base", type: "vec4", default: [0, 0, 0, 1] },
842
+ { name: "Blend", type: "vec4", default: [1, 1, 1, 1] },
843
+ { name: "Opacity", type: "float", default: 1 }
844
+ ],
845
+ outputs: [{ name: "Out", type: "vec4" }],
846
+ properties: [
847
+ {
848
+ name: "Mode",
849
+ type: "dropdown",
850
+ default: "normal",
851
+ options: [
852
+ "normal",
853
+ "multiply",
854
+ "screen",
855
+ "overlay",
856
+ "add",
857
+ "subtract",
858
+ "difference",
859
+ "darken",
860
+ "lighten"
861
+ ]
862
+ }
863
+ ],
864
+ glsl: `
865
+ vec4 {{output.Out}};
866
+ // Blend mode logic here based on prop.Mode
867
+ {{output.Out}} = mix({{input.Base}}, {{input.Blend}}, {{input.Opacity}});
868
+ `
869
+ },
870
+ {
871
+ id: "contrast",
872
+ name: "Contrast",
873
+ category: "color",
874
+ inputs: [
875
+ { name: "In", type: "vec3", default: [0.5, 0.5, 0.5] },
876
+ { name: "Contrast", type: "float", default: 1 }
877
+ ],
878
+ outputs: [{ name: "Out", type: "vec3" }],
879
+ glsl: `vec3 {{output.Out}} = ({{input.In}} - 0.5) * {{input.Contrast}} + 0.5;`
880
+ },
881
+ {
882
+ id: "saturation",
883
+ name: "Saturation",
884
+ category: "color",
885
+ inputs: [
886
+ { name: "In", type: "vec3", default: [0.5, 0.5, 0.5] },
887
+ { name: "Saturation", type: "float", default: 1 }
888
+ ],
889
+ outputs: [{ name: "Out", type: "vec3" }],
890
+ glsl: `
891
+ float luma = dot({{input.In}}, vec3(0.2126, 0.7152, 0.0722));
892
+ vec3 {{output.Out}} = mix(vec3(luma), {{input.In}}, {{input.Saturation}});
893
+ `
894
+ },
895
+ {
896
+ id: "hue",
897
+ name: "Hue",
898
+ category: "color",
899
+ inputs: [
900
+ { name: "In", type: "vec3", default: [1, 0, 0] },
901
+ { name: "Offset", type: "float", default: 0 }
902
+ ],
903
+ outputs: [{ name: "Out", type: "vec3" }],
904
+ glsl: `
905
+ // RGB to HSV
906
+ vec3 hsvIn = {{input.In}};
907
+ float maxC = max(max(hsvIn.r, hsvIn.g), hsvIn.b);
908
+ float minC = min(min(hsvIn.r, hsvIn.g), hsvIn.b);
909
+ float delta = maxC - minC;
910
+ float h = 0.0;
911
+ if (delta > 0.0) {
912
+ if (maxC == hsvIn.r) h = mod((hsvIn.g - hsvIn.b) / delta, 6.0);
913
+ else if (maxC == hsvIn.g) h = (hsvIn.b - hsvIn.r) / delta + 2.0;
914
+ else h = (hsvIn.r - hsvIn.g) / delta + 4.0;
915
+ h /= 6.0;
916
+ }
917
+ float s = maxC > 0.0 ? delta / maxC : 0.0;
918
+ float v = maxC;
919
+
920
+ // Shift hue
921
+ h = fract(h + {{input.Offset}});
922
+
923
+ // HSV to RGB
924
+ float i = floor(h * 6.0);
925
+ float f = h * 6.0 - i;
926
+ float p = v * (1.0 - s);
927
+ float q = v * (1.0 - f * s);
928
+ float t = v * (1.0 - (1.0 - f) * s);
929
+
930
+ vec3 {{output.Out}};
931
+ int im = int(mod(i, 6.0));
932
+ if (im == 0) {{output.Out}} = vec3(v, t, p);
933
+ else if (im == 1) {{output.Out}} = vec3(q, v, p);
934
+ else if (im == 2) {{output.Out}} = vec3(p, v, t);
935
+ else if (im == 3) {{output.Out}} = vec3(p, q, v);
936
+ else if (im == 4) {{output.Out}} = vec3(t, p, v);
937
+ else {{output.Out}} = vec3(v, p, q);
938
+ `
939
+ },
940
+ {
941
+ id: "brightness",
942
+ name: "Brightness",
943
+ category: "color",
944
+ inputs: [
945
+ { name: "In", type: "vec3", default: [0.5, 0.5, 0.5] },
946
+ { name: "Brightness", type: "float", default: 0 }
947
+ ],
948
+ outputs: [{ name: "Out", type: "vec3" }],
949
+ glsl: `vec3 {{output.Out}} = {{input.In}} + {{input.Brightness}};`
950
+ },
951
+ {
952
+ id: "whiteBalance",
953
+ name: "White Balance",
954
+ category: "color",
955
+ inputs: [
956
+ { name: "In", type: "vec3", default: [1, 1, 1] },
957
+ { name: "Temperature", type: "float", default: 0 },
958
+ { name: "Tint", type: "float", default: 0 }
959
+ ],
960
+ outputs: [{ name: "Out", type: "vec3" }],
961
+ glsl: `
962
+ float t = {{input.Temperature}};
963
+ float ti = {{input.Tint}};
964
+ vec3 {{output.Out}} = {{input.In}} + vec3(t, ti, -t);
965
+ `
966
+ },
967
+ {
968
+ id: "channelMixer",
969
+ name: "Channel Mixer",
970
+ category: "color",
971
+ inputs: [{ name: "In", type: "vec3", default: [1, 1, 1] }],
972
+ outputs: [{ name: "Out", type: "vec3" }],
973
+ properties: [
974
+ { name: "Red", type: "vec3", default: [1, 0, 0] },
975
+ { name: "Green", type: "vec3", default: [0, 1, 0] },
976
+ { name: "Blue", type: "vec3", default: [0, 0, 1] }
977
+ ],
978
+ glsl: `
979
+ vec3 {{output.Out}} = vec3(
980
+ dot({{input.In}}, vec3({{prop.Red}})),
981
+ dot({{input.In}}, vec3({{prop.Green}})),
982
+ dot({{input.In}}, vec3({{prop.Blue}}))
983
+ );
984
+ `
985
+ },
986
+ {
987
+ id: "colorGrade",
988
+ name: "Color Grade",
989
+ category: "color",
990
+ description: "Lift-Gamma-Gain color grading",
991
+ inputs: [{ name: "In", type: "vec3", default: [0.5, 0.5, 0.5] }],
992
+ outputs: [{ name: "Out", type: "vec3" }],
993
+ properties: [
994
+ { name: "Lift", type: "color", default: [0, 0, 0, 1] },
995
+ { name: "Gamma", type: "color", default: [0.5, 0.5, 0.5, 1] },
996
+ { name: "Gain", type: "color", default: [1, 1, 1, 1] }
997
+ ],
998
+ glsl: `
999
+ vec3 lift = vec3({{prop.Lift}}.rgb);
1000
+ vec3 gamma = vec3({{prop.Gamma}}.rgb);
1001
+ vec3 gain = vec3({{prop.Gain}}.rgb);
1002
+ vec3 col = {{input.In}} * gain + lift;
1003
+ vec3 {{output.Out}} = pow(col, 1.0 / (gamma * 2.0));
1004
+ `
1005
+ },
1006
+ // ─── Lighting Nodes ──────────────────────────────────────
1007
+ {
1008
+ id: "lambertDiffuse",
1009
+ name: "Lambert Diffuse",
1010
+ category: "lighting",
1011
+ inputs: [
1012
+ { name: "Normal", type: "vec3" },
1013
+ { name: "LightDir", type: "vec3" },
1014
+ { name: "LightColor", type: "vec3", default: [1, 1, 1] }
1015
+ ],
1016
+ outputs: [{ name: "Out", type: "vec3" }],
1017
+ glsl: `
1018
+ float ndotl = max(dot({{input.Normal}}, {{input.LightDir}}), 0.0);
1019
+ vec3 {{output.Out}} = {{input.LightColor}} * ndotl;
1020
+ `
1021
+ },
1022
+ {
1023
+ id: "blinnPhongSpecular",
1024
+ name: "Blinn-Phong Specular",
1025
+ category: "lighting",
1026
+ inputs: [
1027
+ { name: "Normal", type: "vec3" },
1028
+ { name: "ViewDir", type: "vec3" },
1029
+ { name: "LightDir", type: "vec3" },
1030
+ { name: "Smoothness", type: "float", default: 0.5 }
1031
+ ],
1032
+ outputs: [{ name: "Out", type: "float" }],
1033
+ glsl: `
1034
+ vec3 halfDir = normalize({{input.LightDir}} + {{input.ViewDir}});
1035
+ float ndoth = max(dot({{input.Normal}}, halfDir), 0.0);
1036
+ float spec = pow(ndoth, exp2(10.0 * {{input.Smoothness}} + 1.0));
1037
+ float {{output.Out}} = spec;
1038
+ `
1039
+ },
1040
+ {
1041
+ id: "fresnel",
1042
+ name: "Fresnel",
1043
+ category: "lighting",
1044
+ inputs: [
1045
+ { name: "Normal", type: "vec3" },
1046
+ { name: "ViewDir", type: "vec3" },
1047
+ { name: "Power", type: "float", default: 5 }
1048
+ ],
1049
+ outputs: [{ name: "Out", type: "float" }],
1050
+ glsl: `
1051
+ float ndotv = max(dot({{input.Normal}}, {{input.ViewDir}}), 0.0);
1052
+ float {{output.Out}} = pow(1.0 - ndotv, {{input.Power}});
1053
+ `
1054
+ },
1055
+ {
1056
+ id: "ambientOcclusion",
1057
+ name: "Ambient Occlusion",
1058
+ category: "lighting",
1059
+ inputs: [
1060
+ { name: "Color", type: "vec3" },
1061
+ { name: "AO", type: "float", default: 1 },
1062
+ { name: "Intensity", type: "float", default: 1 }
1063
+ ],
1064
+ outputs: [{ name: "Out", type: "vec3" }],
1065
+ glsl: `vec3 {{output.Out}} = {{input.Color}} * mix(1.0, {{input.AO}}, {{input.Intensity}});`
1066
+ },
1067
+ // ─── Procedural Nodes ────────────────────────────────────
1068
+ {
1069
+ id: "noise",
1070
+ name: "Simple Noise",
1071
+ category: "procedural",
1072
+ inputs: [
1073
+ { name: "UV", type: "vec2", default: [0, 0] },
1074
+ { name: "Scale", type: "float", default: 10 }
1075
+ ],
1076
+ outputs: [{ name: "Out", type: "float" }],
1077
+ glsl: `
1078
+ vec2 p = {{input.UV}} * {{input.Scale}};
1079
+ float {{output.Out}} = fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
1080
+ `
1081
+ },
1082
+ {
1083
+ id: "gradient",
1084
+ name: "Gradient Noise",
1085
+ category: "procedural",
1086
+ inputs: [
1087
+ { name: "UV", type: "vec2", default: [0, 0] },
1088
+ { name: "Scale", type: "float", default: 5 }
1089
+ ],
1090
+ outputs: [{ name: "Out", type: "float" }],
1091
+ glsl: `
1092
+ // Simple gradient noise approximation
1093
+ vec2 p = {{input.UV}} * {{input.Scale}};
1094
+ vec2 i = floor(p);
1095
+ vec2 f = fract(p);
1096
+ f = f * f * (3.0 - 2.0 * f);
1097
+
1098
+ float a = fract(sin(dot(i, vec2(12.9898, 78.233))) * 43758.5453);
1099
+ float b = fract(sin(dot(i + vec2(1.0, 0.0), vec2(12.9898, 78.233))) * 43758.5453);
1100
+ float c = fract(sin(dot(i + vec2(0.0, 1.0), vec2(12.9898, 78.233))) * 43758.5453);
1101
+ float d = fract(sin(dot(i + vec2(1.0, 1.0), vec2(12.9898, 78.233))) * 43758.5453);
1102
+
1103
+ float {{output.Out}} = mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
1104
+ `
1105
+ },
1106
+ {
1107
+ id: "voronoi",
1108
+ name: "Voronoi",
1109
+ category: "procedural",
1110
+ inputs: [
1111
+ { name: "UV", type: "vec2", default: [0, 0] },
1112
+ { name: "Scale", type: "float", default: 5 },
1113
+ { name: "Angle", type: "float", default: 0 }
1114
+ ],
1115
+ outputs: [
1116
+ { name: "Out", type: "float" },
1117
+ { name: "Cells", type: "float" }
1118
+ ],
1119
+ glsl: `
1120
+ vec2 p = {{input.UV}} * {{input.Scale}};
1121
+ vec2 n = floor(p);
1122
+ vec2 f = fract(p);
1123
+
1124
+ float minDist = 1.0;
1125
+ vec2 minCell = vec2(0.0);
1126
+
1127
+ for (int j = -1; j <= 1; j++) {
1128
+ for (int i = -1; i <= 1; i++) {
1129
+ vec2 g = vec2(float(i), float(j));
1130
+ vec2 o = fract(sin(vec2(dot(n + g, vec2(12.9898, 78.233)), dot(n + g, vec2(23.4321, 14.5678)))) * 43758.5453);
1131
+ vec2 r = g + o - f;
1132
+ float d = dot(r, r);
1133
+ if (d < minDist) {
1134
+ minDist = d;
1135
+ minCell = n + g + o;
1136
+ }
1137
+ }
1138
+ }
1139
+
1140
+ float {{output.Out}} = minDist;
1141
+ float {{output.Cells}} = fract(sin(dot(minCell, vec2(12.9898, 78.233))) * 43758.5453);
1142
+ `
1143
+ },
1144
+ {
1145
+ id: "checkerboard",
1146
+ name: "Checkerboard",
1147
+ category: "procedural",
1148
+ inputs: [
1149
+ { name: "UV", type: "vec2", default: [0, 0] },
1150
+ { name: "Frequency", type: "vec2", default: [4, 4] }
1151
+ ],
1152
+ outputs: [{ name: "Out", type: "float" }],
1153
+ properties: [
1154
+ { name: "ColorA", type: "color", default: [1, 1, 1, 1] },
1155
+ { name: "ColorB", type: "color", default: [0, 0, 0, 1] }
1156
+ ],
1157
+ glsl: `
1158
+ vec2 uv = {{input.UV}} * {{input.Frequency}};
1159
+ float c = mod(floor(uv.x) + floor(uv.y), 2.0);
1160
+ float {{output.Out}} = c;
1161
+ `
1162
+ },
1163
+ {
1164
+ id: "ellipse",
1165
+ name: "Ellipse",
1166
+ category: "procedural",
1167
+ inputs: [
1168
+ { name: "UV", type: "vec2", default: [0, 0] },
1169
+ { name: "Width", type: "float", default: 0.5 },
1170
+ { name: "Height", type: "float", default: 0.5 }
1171
+ ],
1172
+ outputs: [{ name: "Out", type: "float" }],
1173
+ glsl: `
1174
+ vec2 d = {{input.UV}} - 0.5;
1175
+ d.x /= {{input.Width}};
1176
+ d.y /= {{input.Height}};
1177
+ float {{output.Out}} = 1.0 - smoothstep(0.5, 0.51, length(d));
1178
+ `
1179
+ },
1180
+ {
1181
+ id: "rectangle",
1182
+ name: "Rectangle",
1183
+ category: "procedural",
1184
+ inputs: [
1185
+ { name: "UV", type: "vec2", default: [0, 0] },
1186
+ { name: "Width", type: "float", default: 0.5 },
1187
+ { name: "Height", type: "float", default: 0.5 }
1188
+ ],
1189
+ outputs: [{ name: "Out", type: "float" }],
1190
+ glsl: `
1191
+ vec2 d = abs({{input.UV}} - 0.5);
1192
+ float {{output.Out}} = 1.0 - smoothstep(0.0, 0.01, max(d.x - {{input.Width}} * 0.5, d.y - {{input.Height}} * 0.5));
1193
+ `
1194
+ },
1195
+ {
1196
+ id: "roundedRectangle",
1197
+ name: "Rounded Rectangle",
1198
+ category: "procedural",
1199
+ inputs: [
1200
+ { name: "UV", type: "vec2", default: [0, 0] },
1201
+ { name: "Width", type: "float", default: 0.5 },
1202
+ { name: "Height", type: "float", default: 0.5 },
1203
+ { name: "Radius", type: "float", default: 0.1 }
1204
+ ],
1205
+ outputs: [{ name: "Out", type: "float" }],
1206
+ glsl: `
1207
+ vec2 d = abs({{input.UV}} - 0.5) - vec2({{input.Width}}, {{input.Height}}) * 0.5 + {{input.Radius}};
1208
+ float {{output.Out}} = 1.0 - smoothstep(0.0, 0.01, length(max(d, 0.0)) - {{input.Radius}});
1209
+ `
1210
+ },
1211
+ {
1212
+ id: "polygon",
1213
+ name: "Polygon",
1214
+ category: "procedural",
1215
+ inputs: [
1216
+ { name: "UV", type: "vec2", default: [0, 0] },
1217
+ { name: "Sides", type: "float", default: 6 },
1218
+ { name: "Width", type: "float", default: 0.5 },
1219
+ { name: "Height", type: "float", default: 0.5 }
1220
+ ],
1221
+ outputs: [{ name: "Out", type: "float" }],
1222
+ glsl: `
1223
+ vec2 d = {{input.UV}} - 0.5;
1224
+ float angle = atan(d.y, d.x);
1225
+ float slice = 6.283185 / {{input.Sides}};
1226
+ float dist = cos(floor(0.5 + angle / slice) * slice - angle) * length(d * 2.0 / vec2({{input.Width}}, {{input.Height}}));
1227
+ float {{output.Out}} = 1.0 - smoothstep(1.0, 1.01, dist);
1228
+ `
1229
+ },
1230
+ // ─── Output Nodes ────────────────────────────────────────
1231
+ {
1232
+ id: "pbrMasterNode",
1233
+ name: "PBR Master",
1234
+ category: "output",
1235
+ description: "Physically Based Rendering output",
1236
+ isMaster: true,
1237
+ inputs: [
1238
+ { name: "Albedo", type: "vec3", default: [1, 1, 1] },
1239
+ { name: "Normal", type: "vec3", default: [0, 0, 1] },
1240
+ { name: "Metallic", type: "float", default: 0 },
1241
+ { name: "Smoothness", type: "float", default: 0.5 },
1242
+ { name: "AO", type: "float", default: 1 },
1243
+ { name: "Emission", type: "vec3", default: [0, 0, 0] },
1244
+ { name: "Alpha", type: "float", default: 1 },
1245
+ { name: "AlphaClip", type: "float", default: 0 }
1246
+ ],
1247
+ outputs: [],
1248
+ glsl: `
1249
+ // PBR output
1250
+ gl_FragColor = vec4({{input.Albedo}}, {{input.Alpha}});
1251
+
1252
+ // Normal output
1253
+ normalOutput = {{input.Normal}};
1254
+
1255
+ // Material properties
1256
+ metallicOutput = {{input.Metallic}};
1257
+ smoothnessOutput = {{input.Smoothness}};
1258
+ aoOutput = {{input.AO}};
1259
+ emissionOutput = {{input.Emission}};
1260
+
1261
+ // Alpha clip
1262
+ if ({{input.Alpha}} < {{input.AlphaClip}}) discard;
1263
+ `
1264
+ },
1265
+ {
1266
+ id: "unlitMasterNode",
1267
+ name: "Unlit Master",
1268
+ category: "output",
1269
+ description: "Unlit/emissive output",
1270
+ isMaster: true,
1271
+ inputs: [
1272
+ { name: "Color", type: "vec3", default: [1, 1, 1] },
1273
+ { name: "Alpha", type: "float", default: 1 },
1274
+ { name: "AlphaClip", type: "float", default: 0 }
1275
+ ],
1276
+ outputs: [],
1277
+ glsl: `
1278
+ gl_FragColor = vec4({{input.Color}}, {{input.Alpha}});
1279
+ if ({{input.Alpha}} < {{input.AlphaClip}}) discard;
1280
+ `
1281
+ },
1282
+ {
1283
+ id: "vertexMasterNode",
1284
+ name: "Vertex Master",
1285
+ category: "output",
1286
+ description: "Vertex shader output",
1287
+ isMaster: true,
1288
+ stage: "vertex",
1289
+ inputs: [
1290
+ { name: "Position", type: "vec3" },
1291
+ { name: "Normal", type: "vec3" },
1292
+ { name: "Tangent", type: "vec3" }
1293
+ ],
1294
+ outputs: [],
1295
+ glsl: `
1296
+ gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * vec4({{input.Position}}, 1.0);
1297
+ `
1298
+ }
1316
1299
  ];
1317
1300
  class ShaderCodeGenerator {
1318
- constructor(graph) {
1319
- this.nodeLibrary = new Map();
1320
- this.generatedCode = new Map();
1321
- this.uniforms = [];
1322
- this.defines = [];
1323
- this.nodeCounter = 0;
1324
- this.graph = graph;
1325
- // Build node library lookup
1326
- for (const nodeDef of SHADER_NODE_LIBRARY) {
1327
- this.nodeLibrary.set(nodeDef.id, nodeDef);
1328
- }
1301
+ constructor(graph) {
1302
+ this.nodeLibrary = /* @__PURE__ */ new Map();
1303
+ this.generatedCode = /* @__PURE__ */ new Map();
1304
+ this.uniforms = [];
1305
+ this.defines = [];
1306
+ this.nodeCounter = 0;
1307
+ this.graph = graph;
1308
+ for (const nodeDef of SHADER_NODE_LIBRARY) {
1309
+ this.nodeLibrary.set(nodeDef.id, nodeDef);
1310
+ }
1311
+ }
1312
+ generate() {
1313
+ this.generatedCode.clear();
1314
+ this.uniforms = [];
1315
+ this.defines = [];
1316
+ this.nodeCounter = 0;
1317
+ const masterNode = this.graph.nodes.find((n) => {
1318
+ const def = this.nodeLibrary.get(n.type);
1319
+ return def?.isMaster;
1320
+ });
1321
+ if (!masterNode) {
1322
+ throw new Error("No master node found in shader graph");
1323
+ }
1324
+ const fragmentCode = this.generateNode(masterNode.id);
1325
+ const vertex = this.buildVertexShader();
1326
+ const fragment = this.buildFragmentShader(fragmentCode);
1327
+ return {
1328
+ vertex,
1329
+ fragment,
1330
+ uniforms: this.uniforms,
1331
+ defines: this.defines
1332
+ };
1333
+ }
1334
+ generateNode(nodeId) {
1335
+ if (this.generatedCode.has(nodeId)) {
1336
+ return this.generatedCode.get(nodeId);
1329
1337
  }
1330
- generate() {
1331
- this.generatedCode.clear();
1332
- this.uniforms = [];
1333
- this.defines = [];
1334
- this.nodeCounter = 0;
1335
- // Find master node
1336
- const masterNode = this.graph.nodes.find((n) => {
1337
- const def = this.nodeLibrary.get(n.type);
1338
- return def?.isMaster;
1338
+ const node = this.graph.nodes.find((n) => n.id === nodeId);
1339
+ if (!node) {
1340
+ return "";
1341
+ }
1342
+ const nodeDef = this.nodeLibrary.get(node.type);
1343
+ if (!nodeDef) {
1344
+ return "";
1345
+ }
1346
+ const inputConnections = this.graph.connections.filter((c) => c.to.nodeId === nodeId);
1347
+ const inputCode = [];
1348
+ const inputVars = {};
1349
+ for (const conn of inputConnections) {
1350
+ const sourceCode = this.generateNode(conn.from.nodeId);
1351
+ inputCode.push(sourceCode);
1352
+ inputVars[conn.to.portName] = `node_${conn.from.nodeId}_${conn.from.portName}`;
1353
+ }
1354
+ let code = nodeDef.glsl || "";
1355
+ const varPrefix = `node_${nodeId}`;
1356
+ for (const input of nodeDef.inputs) {
1357
+ const varName = inputVars[input.name] || this.defaultValue(input.type, input.default);
1358
+ code = code.replace(new RegExp(`\\{\\{input\\.${input.name}\\}\\}`, "g"), varName);
1359
+ }
1360
+ for (const output of nodeDef.outputs) {
1361
+ code = code.replace(
1362
+ new RegExp(`\\{\\{output\\.${output.name}\\}\\}`, "g"),
1363
+ `${varPrefix}_${output.name}`
1364
+ );
1365
+ }
1366
+ for (const prop of nodeDef.properties || []) {
1367
+ const value = node.properties[prop.name] ?? prop.default;
1368
+ code = code.replace(
1369
+ new RegExp(`\\{\\{prop\\.${prop.name}\\}\\}`, "g"),
1370
+ this.formatValue(value, prop.type)
1371
+ );
1372
+ if (prop.type === "texture") {
1373
+ this.uniforms.push({
1374
+ name: `${varPrefix}_${prop.name}`,
1375
+ type: "sampler2D"
1339
1376
  });
1340
- if (!masterNode) {
1341
- throw new Error('No master node found in shader graph');
1342
- }
1343
- // Generate from master node backwards
1344
- const fragmentCode = this.generateNode(masterNode.id);
1345
- // Build complete shaders
1346
- const vertex = this.buildVertexShader();
1347
- const fragment = this.buildFragmentShader(fragmentCode);
1348
- return {
1349
- vertex,
1350
- fragment,
1351
- uniforms: this.uniforms,
1352
- defines: this.defines,
1353
- };
1377
+ }
1354
1378
  }
1355
- generateNode(nodeId) {
1356
- // Check if already generated
1357
- if (this.generatedCode.has(nodeId)) {
1358
- return this.generatedCode.get(nodeId);
1359
- }
1360
- const node = this.graph.nodes.find((n) => n.id === nodeId);
1361
- if (!node) {
1362
- return '';
1363
- }
1364
- const nodeDef = this.nodeLibrary.get(node.type);
1365
- if (!nodeDef) {
1366
- return '';
1367
- }
1368
- // Generate dependencies first
1369
- const inputConnections = this.graph.connections.filter((c) => c.to.nodeId === nodeId);
1370
- const inputCode = [];
1371
- const inputVars = {};
1372
- for (const conn of inputConnections) {
1373
- const sourceCode = this.generateNode(conn.from.nodeId);
1374
- inputCode.push(sourceCode);
1375
- inputVars[conn.to.portName] = `node_${conn.from.nodeId}_${conn.from.portName}`;
1376
- }
1377
- // Generate this node's code
1378
- let code = nodeDef.glsl || '';
1379
- const varPrefix = `node_${nodeId}`;
1380
- // Replace input placeholders
1381
- for (const input of nodeDef.inputs) {
1382
- const varName = inputVars[input.name] || this.defaultValue(input.type, input.default);
1383
- code = code.replace(new RegExp(`\\{\\{input\\.${input.name}\\}\\}`, 'g'), varName);
1384
- }
1385
- // Replace output placeholders
1386
- for (const output of nodeDef.outputs) {
1387
- code = code.replace(new RegExp(`\\{\\{output\\.${output.name}\\}\\}`, 'g'), `${varPrefix}_${output.name}`);
1388
- }
1389
- // Replace property placeholders
1390
- for (const prop of nodeDef.properties || []) {
1391
- const value = node.properties[prop.name] ?? prop.default;
1392
- code = code.replace(new RegExp(`\\{\\{prop\\.${prop.name}\\}\\}`, 'g'), this.formatValue(value, prop.type));
1393
- // Add uniform if it's a texture
1394
- if (prop.type === 'texture') {
1395
- this.uniforms.push({
1396
- name: `${varPrefix}_${prop.name}`,
1397
- type: 'sampler2D',
1398
- });
1399
- }
1400
- }
1401
- const fullCode = inputCode.join('\n') + '\n' + code;
1402
- this.generatedCode.set(nodeId, fullCode);
1403
- return fullCode;
1379
+ const fullCode = inputCode.join("\n") + "\n" + code;
1380
+ this.generatedCode.set(nodeId, fullCode);
1381
+ return fullCode;
1382
+ }
1383
+ defaultValue(type, defaultVal) {
1384
+ if (defaultVal !== void 0) {
1385
+ return this.formatValue(defaultVal, type);
1404
1386
  }
1405
- defaultValue(type, defaultVal) {
1406
- if (defaultVal !== undefined) {
1407
- return this.formatValue(defaultVal, type);
1408
- }
1409
- switch (type) {
1410
- case 'float':
1411
- return '0.0';
1412
- case 'vec2':
1413
- return 'vec2(0.0)';
1414
- case 'vec3':
1415
- return 'vec3(0.0)';
1416
- case 'vec4':
1417
- return 'vec4(0.0)';
1418
- case 'int':
1419
- return '0';
1420
- case 'bool':
1421
- return 'false';
1422
- default:
1423
- return '0.0';
1424
- }
1387
+ switch (type) {
1388
+ case "float":
1389
+ return "0.0";
1390
+ case "vec2":
1391
+ return "vec2(0.0)";
1392
+ case "vec3":
1393
+ return "vec3(0.0)";
1394
+ case "vec4":
1395
+ return "vec4(0.0)";
1396
+ case "int":
1397
+ return "0";
1398
+ case "bool":
1399
+ return "false";
1400
+ default:
1401
+ return "0.0";
1425
1402
  }
1426
- formatValue(value, _type) {
1427
- if (Array.isArray(value)) {
1428
- return `vec${value.length}(${value.map((v) => v.toFixed(6)).join(', ')})`;
1429
- }
1430
- if (typeof value === 'number') {
1431
- return value.toFixed(6);
1432
- }
1433
- if (typeof value === 'boolean') {
1434
- return value ? 'true' : 'false';
1435
- }
1436
- return String(value);
1403
+ }
1404
+ formatValue(value, _type) {
1405
+ if (Array.isArray(value)) {
1406
+ return `vec${value.length}(${value.map((v) => v.toFixed(6)).join(", ")})`;
1437
1407
  }
1438
- buildVertexShader() {
1439
- const precision = this.graph.settings.precision;
1440
- return `#version 300 es
1441
- precision ${precision} float;
1442
-
1443
- // Attributes
1444
- in vec3 a_position;
1445
- in vec3 a_normal;
1446
- in vec2 a_uv0;
1447
- in vec2 a_uv1;
1448
- in vec4 a_color;
1449
- in vec3 a_tangent;
1450
-
1451
- // Uniforms
1452
- uniform mat4 u_modelMatrix;
1453
- uniform mat4 u_viewMatrix;
1454
- uniform mat4 u_projectionMatrix;
1455
- uniform mat4 u_normalMatrix;
1456
- uniform mat4 u_worldToObject;
1457
-
1458
- // Varyings
1459
- out vec3 v_worldPosition;
1460
- out vec3 v_objectPosition;
1461
- out vec3 v_viewPosition;
1462
- out vec3 v_worldNormal;
1463
- out vec3 v_objectNormal;
1464
- out vec3 v_viewNormal;
1465
- out vec3 v_tangent;
1466
- out vec3 v_tangentNormal;
1467
- out vec2 v_uv0;
1468
- out vec2 v_uv1;
1469
- out vec2 v_uv2;
1470
- out vec2 v_uv3;
1471
- out vec4 v_color;
1472
-
1473
- void main() {
1474
- vec4 worldPos = u_modelMatrix * vec4(a_position, 1.0);
1475
- vec4 viewPos = u_viewMatrix * worldPos;
1476
-
1477
- v_worldPosition = worldPos.xyz;
1478
- v_objectPosition = a_position;
1479
- v_viewPosition = viewPos.xyz;
1480
-
1481
- v_worldNormal = mat3(u_normalMatrix) * a_normal;
1482
- v_objectNormal = a_normal;
1483
- v_viewNormal = mat3(u_viewMatrix) * v_worldNormal;
1484
-
1485
- v_tangent = mat3(u_normalMatrix) * a_tangent;
1486
- v_tangentNormal = vec3(0.0, 0.0, 1.0);
1487
-
1488
- v_uv0 = a_uv0;
1489
- v_uv1 = a_uv1;
1490
- v_uv2 = a_uv0;
1491
- v_uv3 = a_uv0;
1492
- v_color = a_color;
1493
-
1494
- gl_Position = u_projectionMatrix * viewPos;
1495
- }
1496
- `;
1408
+ if (typeof value === "number") {
1409
+ return value.toFixed(6);
1497
1410
  }
1498
- buildFragmentShader(mainCode) {
1499
- const precision = this.graph.settings.precision;
1500
- const uniformDecls = this.uniforms.map((u) => `uniform ${u.type} ${u.name};`).join('\n');
1501
- return `#version 300 es
1502
- precision ${precision} float;
1503
-
1504
- // Varyings
1505
- in vec3 v_worldPosition;
1506
- in vec3 v_objectPosition;
1507
- in vec3 v_viewPosition;
1508
- in vec3 v_worldNormal;
1509
- in vec3 v_objectNormal;
1510
- in vec3 v_viewNormal;
1511
- in vec3 v_tangent;
1512
- in vec3 v_tangentNormal;
1513
- in vec2 v_uv0;
1514
- in vec2 v_uv1;
1515
- in vec2 v_uv2;
1516
- in vec2 v_uv3;
1517
- in vec4 v_color;
1518
-
1519
- // Global uniforms
1520
- uniform float u_time;
1521
- uniform float u_deltaTime;
1522
- uniform float u_smoothDeltaTime;
1523
- uniform vec3 u_cameraPosition;
1524
- uniform vec2 u_resolution;
1525
-
1526
- // Material uniforms
1527
- ${uniformDecls}
1528
-
1529
- // Outputs
1530
- out vec4 fragColor;
1531
-
1532
- void main() {
1533
- ${mainCode}
1534
- fragColor = gl_FragColor;
1535
- }
1536
- `;
1411
+ if (typeof value === "boolean") {
1412
+ return value ? "true" : "false";
1537
1413
  }
1414
+ return String(value);
1415
+ }
1416
+ buildVertexShader() {
1417
+ const precision = this.graph.settings.precision;
1418
+ return `#version 300 es
1419
+ precision ${precision} float;
1420
+
1421
+ // Attributes
1422
+ in vec3 a_position;
1423
+ in vec3 a_normal;
1424
+ in vec2 a_uv0;
1425
+ in vec2 a_uv1;
1426
+ in vec4 a_color;
1427
+ in vec3 a_tangent;
1428
+
1429
+ // Uniforms
1430
+ uniform mat4 u_modelMatrix;
1431
+ uniform mat4 u_viewMatrix;
1432
+ uniform mat4 u_projectionMatrix;
1433
+ uniform mat4 u_normalMatrix;
1434
+ uniform mat4 u_worldToObject;
1435
+
1436
+ // Varyings
1437
+ out vec3 v_worldPosition;
1438
+ out vec3 v_objectPosition;
1439
+ out vec3 v_viewPosition;
1440
+ out vec3 v_worldNormal;
1441
+ out vec3 v_objectNormal;
1442
+ out vec3 v_viewNormal;
1443
+ out vec3 v_tangent;
1444
+ out vec3 v_tangentNormal;
1445
+ out vec2 v_uv0;
1446
+ out vec2 v_uv1;
1447
+ out vec2 v_uv2;
1448
+ out vec2 v_uv3;
1449
+ out vec4 v_color;
1450
+
1451
+ void main() {
1452
+ vec4 worldPos = u_modelMatrix * vec4(a_position, 1.0);
1453
+ vec4 viewPos = u_viewMatrix * worldPos;
1454
+
1455
+ v_worldPosition = worldPos.xyz;
1456
+ v_objectPosition = a_position;
1457
+ v_viewPosition = viewPos.xyz;
1458
+
1459
+ v_worldNormal = mat3(u_normalMatrix) * a_normal;
1460
+ v_objectNormal = a_normal;
1461
+ v_viewNormal = mat3(u_viewMatrix) * v_worldNormal;
1462
+
1463
+ v_tangent = mat3(u_normalMatrix) * a_tangent;
1464
+ v_tangentNormal = vec3(0.0, 0.0, 1.0);
1465
+
1466
+ v_uv0 = a_uv0;
1467
+ v_uv1 = a_uv1;
1468
+ v_uv2 = a_uv0;
1469
+ v_uv3 = a_uv0;
1470
+ v_color = a_color;
1471
+
1472
+ gl_Position = u_projectionMatrix * viewPos;
1473
+ }
1474
+ `;
1475
+ }
1476
+ buildFragmentShader(mainCode) {
1477
+ const precision = this.graph.settings.precision;
1478
+ const uniformDecls = this.uniforms.map((u) => `uniform ${u.type} ${u.name};`).join("\n");
1479
+ return `#version 300 es
1480
+ precision ${precision} float;
1481
+
1482
+ // Varyings
1483
+ in vec3 v_worldPosition;
1484
+ in vec3 v_objectPosition;
1485
+ in vec3 v_viewPosition;
1486
+ in vec3 v_worldNormal;
1487
+ in vec3 v_objectNormal;
1488
+ in vec3 v_viewNormal;
1489
+ in vec3 v_tangent;
1490
+ in vec3 v_tangentNormal;
1491
+ in vec2 v_uv0;
1492
+ in vec2 v_uv1;
1493
+ in vec2 v_uv2;
1494
+ in vec2 v_uv3;
1495
+ in vec4 v_color;
1496
+
1497
+ // Global uniforms
1498
+ uniform float u_time;
1499
+ uniform float u_deltaTime;
1500
+ uniform float u_smoothDeltaTime;
1501
+ uniform vec3 u_cameraPosition;
1502
+ uniform vec2 u_resolution;
1503
+
1504
+ // Material uniforms
1505
+ ${uniformDecls}
1506
+
1507
+ // Outputs
1508
+ out vec4 fragColor;
1509
+
1510
+ void main() {
1511
+ ${mainCode}
1512
+ fragColor = gl_FragColor;
1513
+ }
1514
+ `;
1515
+ }
1538
1516
  }
1539
1517
  function createShaderGraphEditorState(graph) {
1540
- return {
1541
- graph: graph ?? createEmptyShaderGraph(),
1542
- selectedNodes: [],
1543
- hoveredNode: null,
1544
- hoveredPort: null,
1545
- draggingConnection: null,
1546
- viewOffset: { x: 0, y: 0 },
1547
- zoom: 1,
1548
- previewEnabled: true,
1549
- generatedShader: null,
1550
- compileErrors: [],
1551
- };
1518
+ return {
1519
+ graph: graph ?? createEmptyShaderGraph(),
1520
+ selectedNodes: [],
1521
+ hoveredNode: null,
1522
+ hoveredPort: null,
1523
+ draggingConnection: null,
1524
+ viewOffset: { x: 0, y: 0 },
1525
+ zoom: 1,
1526
+ previewEnabled: true,
1527
+ generatedShader: null,
1528
+ compileErrors: []
1529
+ };
1552
1530
  }
1553
1531
  function createEmptyShaderGraph() {
1554
- return {
1555
- id: `shader_${Date.now()}`,
1556
- name: 'New Shader',
1557
- target: 'glsl',
1558
- stage: 'fragment',
1559
- nodes: [
1560
- {
1561
- id: 'master',
1562
- type: 'pbrMasterNode',
1563
- position: { x: 600, y: 200 },
1564
- properties: {},
1565
- },
1566
- ],
1567
- connections: [],
1568
- properties: [],
1569
- settings: {
1570
- precision: 'highp',
1571
- blendMode: 'opaque',
1572
- cullMode: 'back',
1573
- depthWrite: true,
1574
- depthTest: 'lequal',
1575
- castShadows: true,
1576
- receiveShadows: true,
1577
- doubleSided: false,
1578
- surfaceType: 'opaque',
1579
- renderQueue: 2000,
1580
- },
1581
- };
1532
+ return {
1533
+ id: `shader_${Date.now()}`,
1534
+ name: "New Shader",
1535
+ target: "glsl",
1536
+ stage: "fragment",
1537
+ nodes: [
1538
+ {
1539
+ id: "master",
1540
+ type: "pbrMasterNode",
1541
+ position: { x: 600, y: 200 },
1542
+ properties: {}
1543
+ }
1544
+ ],
1545
+ connections: [],
1546
+ properties: [],
1547
+ settings: {
1548
+ precision: "highp",
1549
+ blendMode: "opaque",
1550
+ cullMode: "back",
1551
+ depthWrite: true,
1552
+ depthTest: "lequal",
1553
+ castShadows: true,
1554
+ receiveShadows: true,
1555
+ doubleSided: false,
1556
+ surfaceType: "opaque",
1557
+ renderQueue: 2e3
1558
+ }
1559
+ };
1582
1560
  }
1583
- // ============================================================
1584
- // Factory Functions
1585
- // ============================================================
1586
- function createShaderGraph(name, target = 'glsl') {
1587
- const graph = createEmptyShaderGraph();
1588
- graph.name = name;
1589
- graph.target = target;
1590
- return graph;
1561
+ function createShaderGraph(name, target = "glsl") {
1562
+ const graph = createEmptyShaderGraph();
1563
+ graph.name = name;
1564
+ graph.target = target;
1565
+ return graph;
1591
1566
  }
1592
1567
  function generateShader(graph) {
1593
- const generator = new ShaderCodeGenerator(graph);
1594
- return generator.generate();
1568
+ const generator = new ShaderCodeGenerator(graph);
1569
+ return generator.generate();
1595
1570
  }
1596
1571
  function getNodeLibrary() {
1597
- return SHADER_NODE_LIBRARY;
1572
+ return SHADER_NODE_LIBRARY;
1598
1573
  }
1599
1574
  function getNodesByCategory(category) {
1600
- return SHADER_NODE_LIBRARY.filter((n) => n.category === category);
1575
+ return SHADER_NODE_LIBRARY.filter((n) => n.category === category);
1601
1576
  }
1602
1577
  function findNodeDef(nodeType) {
1603
- return SHADER_NODE_LIBRARY.find((n) => n.id === nodeType);
1578
+ return SHADER_NODE_LIBRARY.find((n) => n.id === nodeType);
1604
1579
  }
1605
-
1606
- export { SHADER_NODE_LIBRARY, ShaderCodeGenerator, createEmptyShaderGraph, createShaderGraph, createShaderGraphEditorState, findNodeDef, generateShader, getNodeLibrary, getNodesByCategory };
1580
+ export {
1581
+ SHADER_NODE_LIBRARY,
1582
+ ShaderCodeGenerator,
1583
+ createEmptyShaderGraph,
1584
+ createShaderGraph,
1585
+ createShaderGraphEditorState,
1586
+ findNodeDef,
1587
+ generateShader,
1588
+ getNodeLibrary,
1589
+ getNodesByCategory
1590
+ };