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