cuju-render 0.1.0__py3-none-any.whl

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 (382) hide show
  1. cuju/render/__init__.py +759 -0
  2. cuju/render/__main__.py +1065 -0
  3. cuju/render/_export/__init__.py +3 -0
  4. cuju/render/_export/feed.py +542 -0
  5. cuju/render/_export/sizes.py +157 -0
  6. cuju/render/_export/video.py +1618 -0
  7. cuju/render/_export/video_jobs.py +408 -0
  8. cuju/render/_format/__init__.py +3 -0
  9. cuju/render/_format/annotations.py +235 -0
  10. cuju/render/_format/codec.py +307 -0
  11. cuju/render/_format/keep.py +121 -0
  12. cuju/render/_format/recording.py +860 -0
  13. cuju/render/_format/writer.py +54 -0
  14. cuju/render/_guide/__init__.py +3 -0
  15. cuju/render/_guide/doctor.py +523 -0
  16. cuju/render/_guide/help.py +62 -0
  17. cuju/render/_guide/tutorial.py +254 -0
  18. cuju/render/_http/__init__.py +3 -0
  19. cuju/render/_http/commands.py +57 -0
  20. cuju/render/_http/headers.py +103 -0
  21. cuju/render/_http/launch.py +500 -0
  22. cuju/render/_http/launchers.py +408 -0
  23. cuju/render/_http/pwa.py +128 -0
  24. cuju/render/_http/server.py +2105 -0
  25. cuju/render/_http/window.py +360 -0
  26. cuju/render/_moments/__init__.py +3 -0
  27. cuju/render/_moments/captions.py +284 -0
  28. cuju/render/_moments/events.py +1123 -0
  29. cuju/render/_moments/search.py +694 -0
  30. cuju/render/_packages/__init__.py +3 -0
  31. cuju/render/_packages/glsl.py +746 -0
  32. cuju/render/_packages/loudness.py +334 -0
  33. cuju/render/_packages/pack.py +1959 -0
  34. cuju/render/_packages/presentation.py +1376 -0
  35. cuju/render/_packages/vocabulary.py +609 -0
  36. cuju/render/_playing/__init__.py +3 -0
  37. cuju/render/_playing/achievements.py +463 -0
  38. cuju/render/_playing/bench.py +609 -0
  39. cuju/render/_playing/challenges.py +1813 -0
  40. cuju/render/_playing/demo.py +323 -0
  41. cuju/render/_playing/draw.py +211 -0
  42. cuju/render/_playing/errors.py +20 -0
  43. cuju/render/_playing/game.py +645 -0
  44. cuju/render/_playing/limits.py +339 -0
  45. cuju/render/_playing/play.py +926 -0
  46. cuju/render/_playing/policy_worker.py +250 -0
  47. cuju/render/_playing/strict.py +810 -0
  48. cuju/render/_registry/__init__.py +3 -0
  49. cuju/render/_registry/clips.py +394 -0
  50. cuju/render/_registry/joints.py +108 -0
  51. cuju/render/_registry/teams.py +2058 -0
  52. cuju/render/_store/__init__.py +3 -0
  53. cuju/render/_store/home.py +70 -0
  54. cuju/render/_store/library.py +604 -0
  55. cuju/render/_store/samples.py +163 -0
  56. cuju/render/_text/__init__.py +3 -0
  57. cuju/render/_text/languages.py +637 -0
  58. cuju/render/_text/messages.py +1396 -0
  59. cuju/render/_tournaments/__init__.py +3 -0
  60. cuju/render/_tournaments/results.py +547 -0
  61. cuju/render/_tournaments/tournament.py +2742 -0
  62. cuju/render/_tournaments/tournament_cli.py +587 -0
  63. cuju/render/_tournaments/tournament_runner.py +1975 -0
  64. cuju/render/_version.py +6 -0
  65. cuju/render/_watch/__init__.py +3 -0
  66. cuju/render/_watch/grid.py +265 -0
  67. cuju/render/_watch/live.py +664 -0
  68. cuju/render/_watch/notebook.py +79 -0
  69. cuju/render/_watch/show.py +171 -0
  70. cuju/render/samples/sample-11v11.cjr +0 -0
  71. cuju/render/samples/sample-5v5.cjr +0 -0
  72. cuju/render/samples/teams/starter/main.py +33 -0
  73. cuju/render/scenarios/benchmark_full_game_11_vs_11_easy.py +46 -0
  74. cuju/render/scenarios/benchmark_full_game_11_vs_11_hard.py +46 -0
  75. cuju/render/scenarios/benchmark_full_game_11_vs_11_medium.py +46 -0
  76. cuju/render/scenarios/benchmark_full_game_5_vs_5_easy.py +34 -0
  77. cuju/render/scenarios/benchmark_full_game_5_vs_5_hard.py +34 -0
  78. cuju/render/scenarios/benchmark_full_game_5_vs_5_medium.py +34 -0
  79. cuju/render/web/assets/adboard_polygon.webp +0 -0
  80. cuju/render/web/assets/adboard_your_ad_here.webp +0 -0
  81. cuju/render/web/assets/animations/kaykit-rig-medium-combatmelee.glb +0 -0
  82. cuju/render/web/assets/animations/kaykit-rig-medium-general.glb +0 -0
  83. cuju/render/web/assets/animations/kaykit-rig-medium-movementadvanced.glb +0 -0
  84. cuju/render/web/assets/animations/kaykit-rig-medium-movementbasic.glb +0 -0
  85. cuju/render/web/assets/animations/kaykit-rig-medium-simulation.glb +0 -0
  86. cuju/render/web/assets/animations/kaykit-rig-medium-special.glb +0 -0
  87. cuju/render/web/assets/ball.glb +0 -0
  88. cuju/render/web/assets/challenges/3_vs_1_with_keeper.mp4 +0 -0
  89. cuju/render/web/assets/challenges/3_vs_1_with_keeper.webp +0 -0
  90. cuju/render/web/assets/challenges/corner.mp4 +0 -0
  91. cuju/render/web/assets/challenges/corner.webp +0 -0
  92. cuju/render/web/assets/challenges/counterattack_easy.mp4 +0 -0
  93. cuju/render/web/assets/challenges/counterattack_easy.webp +0 -0
  94. cuju/render/web/assets/challenges/counterattack_hard.mp4 +0 -0
  95. cuju/render/web/assets/challenges/counterattack_hard.webp +0 -0
  96. cuju/render/web/assets/challenges/empty_goal.mp4 +0 -0
  97. cuju/render/web/assets/challenges/empty_goal.webp +0 -0
  98. cuju/render/web/assets/challenges/empty_goal_close.mp4 +0 -0
  99. cuju/render/web/assets/challenges/empty_goal_close.webp +0 -0
  100. cuju/render/web/assets/challenges/manifest.json +375 -0
  101. cuju/render/web/assets/challenges/one_on_one.mp4 +0 -0
  102. cuju/render/web/assets/challenges/one_on_one.webp +0 -0
  103. cuju/render/web/assets/challenges/one_on_one_hard.mp4 +0 -0
  104. cuju/render/web/assets/challenges/one_on_one_hard.webp +0 -0
  105. cuju/render/web/assets/challenges/pass_and_shoot_with_keeper.mp4 +0 -0
  106. cuju/render/web/assets/challenges/pass_and_shoot_with_keeper.webp +0 -0
  107. cuju/render/web/assets/challenges/run_pass_and_shoot_with_keeper.mp4 +0 -0
  108. cuju/render/web/assets/challenges/run_pass_and_shoot_with_keeper.webp +0 -0
  109. cuju/render/web/assets/challenges/run_to_score.mp4 +0 -0
  110. cuju/render/web/assets/challenges/run_to_score.webp +0 -0
  111. cuju/render/web/assets/challenges/run_to_score_with_keeper.mp4 +0 -0
  112. cuju/render/web/assets/challenges/run_to_score_with_keeper.webp +0 -0
  113. cuju/render/web/assets/challenges/single_goal_versus_lazy.mp4 +0 -0
  114. cuju/render/web/assets/challenges/single_goal_versus_lazy.webp +0 -0
  115. cuju/render/web/assets/crowd.webp +0 -0
  116. cuju/render/web/assets/crowd_normal.webp +0 -0
  117. cuju/render/web/assets/cuju-logo-384.png +0 -0
  118. cuju/render/web/assets/cuju-logo.png +0 -0
  119. cuju/render/web/assets/cuju-logo.svg +46 -0
  120. cuju/render/web/assets/cuju-mark-light.svg +33 -0
  121. cuju/render/web/assets/cuju-mark.svg +33 -0
  122. cuju/render/web/assets/goal.glb +0 -0
  123. cuju/render/web/assets/grass.webp +0 -0
  124. cuju/render/web/assets/hair_black.png +0 -0
  125. cuju/render/web/assets/hair_blonde.png +0 -0
  126. cuju/render/web/assets/hair_brown.png +0 -0
  127. cuju/render/web/assets/hair_darkblonde.png +0 -0
  128. cuju/render/web/assets/hair_long01.glb +0 -0
  129. cuju/render/web/assets/hair_long02.glb +0 -0
  130. cuju/render/web/assets/hair_medium01.glb +0 -0
  131. cuju/render/web/assets/hair_red.png +0 -0
  132. cuju/render/web/assets/hair_short01.glb +0 -0
  133. cuju/render/web/assets/hair_short02.glb +0 -0
  134. cuju/render/web/assets/icons/cuju-192.png +0 -0
  135. cuju/render/web/assets/icons/cuju-512.png +0 -0
  136. cuju/render/web/assets/icons/cuju-maskable-512.png +0 -0
  137. cuju/render/web/assets/kit_goalkeeper.webp +0 -0
  138. cuju/render/web/assets/kit_mask.png +0 -0
  139. cuju/render/web/assets/kit_normal.webp +0 -0
  140. cuju/render/web/assets/manifest.json +601 -0
  141. cuju/render/web/assets/models/kaykit-barbarian.glb +0 -0
  142. cuju/render/web/assets/models/kaykit-barbarian.json +23 -0
  143. cuju/render/web/assets/models/kaykit-knight.glb +0 -0
  144. cuju/render/web/assets/models/kaykit-knight.json +23 -0
  145. cuju/render/web/assets/models/kaykit-mage.glb +0 -0
  146. cuju/render/web/assets/models/kaykit-mage.json +23 -0
  147. cuju/render/web/assets/models/kaykit-mannequin-medium.glb +0 -0
  148. cuju/render/web/assets/models/kaykit-mannequin-medium.json +23 -0
  149. cuju/render/web/assets/models/kaykit-ranger.glb +0 -0
  150. cuju/render/web/assets/models/kaykit-ranger.json +23 -0
  151. cuju/render/web/assets/models/kaykit-rogue-hooded.glb +0 -0
  152. cuju/render/web/assets/models/kaykit-rogue-hooded.json +23 -0
  153. cuju/render/web/assets/models/kaykit-rogue.glb +0 -0
  154. cuju/render/web/assets/models/kaykit-rogue.json +23 -0
  155. cuju/render/web/assets/models/kaykit-skeleton-mage.glb +0 -0
  156. cuju/render/web/assets/models/kaykit-skeleton-mage.json +23 -0
  157. cuju/render/web/assets/models/kaykit-skeleton-minion.glb +0 -0
  158. cuju/render/web/assets/models/kaykit-skeleton-minion.json +23 -0
  159. cuju/render/web/assets/models/kaykit-skeleton-rogue.glb +0 -0
  160. cuju/render/web/assets/models/kaykit-skeleton-rogue.json +23 -0
  161. cuju/render/web/assets/models/kaykit-skeleton-warrior.glb +0 -0
  162. cuju/render/web/assets/models/kaykit-skeleton-warrior.json +23 -0
  163. cuju/render/web/assets/pitch.webp +0 -0
  164. cuju/render/web/assets/pitch_normal.webp +0 -0
  165. cuju/render/web/assets/player.glb +0 -0
  166. cuju/render/web/assets/shoe.webp +0 -0
  167. cuju/render/web/assets/shoe_sole.png +0 -0
  168. cuju/render/web/assets/skin_01.png +0 -0
  169. cuju/render/web/assets/skin_02.png +0 -0
  170. cuju/render/web/assets/skin_03.png +0 -0
  171. cuju/render/web/assets/skin_04.png +0 -0
  172. cuju/render/web/assets/sounds/applause.ogg +0 -0
  173. cuju/render/web/assets/sounds/beach-wave-1.ogg +0 -0
  174. cuju/render/web/assets/sounds/beach-wave-2.ogg +0 -0
  175. cuju/render/web/assets/sounds/beach-wave-3.ogg +0 -0
  176. cuju/render/web/assets/sounds/beach-wave-4.ogg +0 -0
  177. cuju/render/web/assets/sounds/city-horn.ogg +0 -0
  178. cuju/render/web/assets/sounds/city-loop.ogg +0 -0
  179. cuju/render/web/assets/sounds/city-siren.ogg +0 -0
  180. cuju/render/web/assets/sounds/crowd-cheer.ogg +0 -0
  181. cuju/render/web/assets/sounds/crowd-loop.ogg +0 -0
  182. cuju/render/web/assets/sounds/crowd-ooh.ogg +0 -0
  183. cuju/render/web/assets/sounds/gulls.ogg +0 -0
  184. cuju/render/web/assets/sounds/neon-sting.ogg +0 -0
  185. cuju/render/web/assets/sounds/rain-loop.ogg +0 -0
  186. cuju/render/web/assets/sounds/sounds.json +46 -0
  187. cuju/render/web/assets/sounds/space-beep.ogg +0 -0
  188. cuju/render/web/assets/sounds/space-hum.ogg +0 -0
  189. cuju/render/web/assets/sounds/space-radio.ogg +0 -0
  190. cuju/render/web/assets/sounds/whistle-long.ogg +0 -0
  191. cuju/render/web/assets/sounds/whistle-short.ogg +0 -0
  192. cuju/render/web/assets/sounds/wind-loop.ogg +0 -0
  193. cuju/render/web/easy.css +357 -0
  194. cuju/render/web/export.html +23 -0
  195. cuju/render/web/feed.css +262 -0
  196. cuju/render/web/feed.html +28 -0
  197. cuju/render/web/flat.css +120 -0
  198. cuju/render/web/home.css +837 -0
  199. cuju/render/web/index.html +373 -0
  200. cuju/render/web/js/boot.js +50 -0
  201. cuju/render/web/js/broadcast/audio.js +2141 -0
  202. cuju/render/web/js/broadcast/celebrate.js +1238 -0
  203. cuju/render/web/js/broadcast/decisions.js +609 -0
  204. cuju/render/web/js/broadcast/hud.js +352 -0
  205. cuju/render/web/js/broadcast/show.js +3614 -0
  206. cuju/render/web/js/broadcast/transition.js +2231 -0
  207. cuju/render/web/js/broadcast/voices.js +153 -0
  208. cuju/render/web/js/capture.js +101 -0
  209. cuju/render/web/js/core/accessibility.js +90 -0
  210. cuju/render/web/js/core/api.js +429 -0
  211. cuju/render/web/js/core/comfort.js +135 -0
  212. cuju/render/web/js/core/i18n.js +705 -0
  213. cuju/render/web/js/core/icons.js +167 -0
  214. cuju/render/web/js/core/input-settings.js +156 -0
  215. cuju/render/web/js/core/keys.js +277 -0
  216. cuju/render/web/js/core/language-ui.js +125 -0
  217. cuju/render/web/js/core/menu.js +853 -0
  218. cuju/render/web/js/core/names.js +113 -0
  219. cuju/render/web/js/core/page-structure.js +110 -0
  220. cuju/render/web/js/core/scenarios.js +109 -0
  221. cuju/render/web/js/core/spoilers.js +236 -0
  222. cuju/render/web/js/core/typeahead.js +38 -0
  223. cuju/render/web/js/export/dom-picture.js +330 -0
  224. cuju/render/web/js/export/export-host.js +97 -0
  225. cuju/render/web/js/export/feed-dialog.js +191 -0
  226. cuju/render/web/js/export/feed-params.js +266 -0
  227. cuju/render/web/js/export/feed.js +363 -0
  228. cuju/render/web/js/export/mp4-mux.js +295 -0
  229. cuju/render/web/js/export/photo-core.js +313 -0
  230. cuju/render/web/js/export/photo.js +1314 -0
  231. cuju/render/web/js/export/safe-frame.js +59 -0
  232. cuju/render/web/js/export/size-fields.js +103 -0
  233. cuju/render/web/js/export/sizes.js +178 -0
  234. cuju/render/web/js/export/video-boot.js +55 -0
  235. cuju/render/web/js/export/video-browser.js +325 -0
  236. cuju/render/web/js/export/video-export.js +417 -0
  237. cuju/render/web/js/export/video-plan.js +207 -0
  238. cuju/render/web/js/export/video-range.js +185 -0
  239. cuju/render/web/js/export/webm-mux.js +198 -0
  240. cuju/render/web/js/feed-boot.js +151 -0
  241. cuju/render/web/js/feed-frame.js +101 -0
  242. cuju/render/web/js/help/doctor.js +488 -0
  243. cuju/render/web/js/help/firstrun.js +379 -0
  244. cuju/render/web/js/help/help-center.js +438 -0
  245. cuju/render/web/js/help/install-offer.js +164 -0
  246. cuju/render/web/js/help/install-state.js +104 -0
  247. cuju/render/web/js/help/lessons-core.js +207 -0
  248. cuju/render/web/js/help/lessons.js +463 -0
  249. cuju/render/web/js/help/palette.js +584 -0
  250. cuju/render/web/js/help/pwa.js +257 -0
  251. cuju/render/web/js/help/tour-core.js +241 -0
  252. cuju/render/web/js/help/tour.js +461 -0
  253. cuju/render/web/js/main.js +2513 -0
  254. cuju/render/web/js/pages/draw.js +188 -0
  255. cuju/render/web/js/pages/fieldpage.js +530 -0
  256. cuju/render/web/js/pages/home.js +521 -0
  257. cuju/render/web/js/pages/matches.js +779 -0
  258. cuju/render/web/js/pages/moments-ui.js +359 -0
  259. cuju/render/web/js/pages/queue-filters.js +63 -0
  260. cuju/render/web/js/pages/recording-groups.js +80 -0
  261. cuju/render/web/js/pages/recordings.js +1069 -0
  262. cuju/render/web/js/play/bench.js +347 -0
  263. cuju/render/web/js/play/challenges.js +1302 -0
  264. cuju/render/web/js/play/medals.js +127 -0
  265. cuju/render/web/js/play/play.js +1953 -0
  266. cuju/render/web/js/play/teasers.js +196 -0
  267. cuju/render/web/js/play/touch.js +350 -0
  268. cuju/render/web/js/play/tournament-layout.js +487 -0
  269. cuju/render/web/js/play/tournament-results.js +441 -0
  270. cuju/render/web/js/play/tournament-strict.js +560 -0
  271. cuju/render/web/js/play/tournament.js +2585 -0
  272. cuju/render/web/js/players/animate.js +972 -0
  273. cuju/render/web/js/players/clips.js +224 -0
  274. cuju/render/web/js/players/kaykit.js +162 -0
  275. cuju/render/web/js/players/kits.js +676 -0
  276. cuju/render/web/js/players/number-patch.js +82 -0
  277. cuju/render/web/js/players/players.js +2694 -0
  278. cuju/render/web/js/players/recolor.js +893 -0
  279. cuju/render/web/js/players/retarget.js +325 -0
  280. cuju/render/web/js/players/rig-numbers.js +174 -0
  281. cuju/render/web/js/presentation/animator.js +231 -0
  282. cuju/render/web/js/presentation/assign.js +85 -0
  283. cuju/render/web/js/presentation/behaviors.js +440 -0
  284. cuju/render/web/js/presentation/budget.js +209 -0
  285. cuju/render/web/js/presentation/catalog.js +1674 -0
  286. cuju/render/web/js/presentation/clocks.js +72 -0
  287. cuju/render/web/js/presentation/commands.js +301 -0
  288. cuju/render/web/js/presentation/contract.js +240 -0
  289. cuju/render/web/js/presentation/effects.js +904 -0
  290. cuju/render/web/js/presentation/flash.js +605 -0
  291. cuju/render/web/js/presentation/freeze-worklet.js +22 -0
  292. cuju/render/web/js/presentation/glsl.js +464 -0
  293. cuju/render/web/js/presentation/host.js +323 -0
  294. cuju/render/web/js/presentation/index.js +2066 -0
  295. cuju/render/web/js/presentation/loudness-worklet.js +235 -0
  296. cuju/render/web/js/presentation/loudness.js +740 -0
  297. cuju/render/web/js/presentation/moments.js +536 -0
  298. cuju/render/web/js/presentation/post.js +327 -0
  299. cuju/render/web/js/presentation/preview.js +180 -0
  300. cuju/render/web/js/presentation/protocol.js +174 -0
  301. cuju/render/web/js/presentation/reach.js +158 -0
  302. cuju/render/web/js/presentation/rigging.js +130 -0
  303. cuju/render/web/js/presentation/sandbox.js +157 -0
  304. cuju/render/web/js/presentation/shaders.js +235 -0
  305. cuju/render/web/js/presentation/stage.js +402 -0
  306. cuju/render/web/js/presentation/teamaudio.js +722 -0
  307. cuju/render/web/js/presentation/tracks.js +197 -0
  308. cuju/render/web/js/presentation/values.js +81 -0
  309. cuju/render/web/js/recording/annotation-data.js +203 -0
  310. cuju/render/web/js/recording/captions.js +491 -0
  311. cuju/render/web/js/recording/codec.js +185 -0
  312. cuju/render/web/js/recording/decode-worker.js +70 -0
  313. cuju/render/web/js/recording/decode.js +94 -0
  314. cuju/render/web/js/recording/episodes.js +46 -0
  315. cuju/render/web/js/recording/format.js +461 -0
  316. cuju/render/web/js/recording/live.js +348 -0
  317. cuju/render/web/js/recording/moments-query.js +59 -0
  318. cuju/render/web/js/recording/moments.js +149 -0
  319. cuju/render/web/js/recording/pose.js +86 -0
  320. cuju/render/web/js/recording/timeline.js +275 -0
  321. cuju/render/web/js/teams/art.js +50 -0
  322. cuju/render/web/js/teams/clip-editor.js +293 -0
  323. cuju/render/web/js/teams/editor.js +1979 -0
  324. cuju/render/web/js/teams/library.js +344 -0
  325. cuju/render/web/js/teams/painter.js +633 -0
  326. cuju/render/web/js/teams/surprise-ui.js +195 -0
  327. cuju/render/web/js/teams/surprise.js +497 -0
  328. cuju/render/web/js/teams/team-check.js +127 -0
  329. cuju/render/web/js/watch/annotations.js +270 -0
  330. cuju/render/web/js/watch/flat.js +366 -0
  331. cuju/render/web/js/watch/grid.js +436 -0
  332. cuju/render/web/js/watch/pitch2d.js +289 -0
  333. cuju/render/web/js/watch/player-tools.js +192 -0
  334. cuju/render/web/js/watch/presets.js +201 -0
  335. cuju/render/web/js/world/arenas.js +997 -0
  336. cuju/render/web/js/world/ball.js +204 -0
  337. cuju/render/web/js/world/cameras.js +982 -0
  338. cuju/render/web/js/world/crowd.js +376 -0
  339. cuju/render/web/js/world/field.js +227 -0
  340. cuju/render/web/js/world/framing.js +145 -0
  341. cuju/render/web/js/world/occlusion.js +48 -0
  342. cuju/render/web/js/world/pitch.js +703 -0
  343. cuju/render/web/js/world/scene.js +395 -0
  344. cuju/render/web/js/world/sky.js +325 -0
  345. cuju/render/web/js/world/stadium.js +1262 -0
  346. cuju/render/web/js/world/vendor-sky.js +367 -0
  347. cuju/render/web/js/world/weather.js +264 -0
  348. cuju/render/web/languages/en.json +4750 -0
  349. cuju/render/web/lessons.json +137 -0
  350. cuju/render/web/manifest.webmanifest +23 -0
  351. cuju/render/web/style.css +8399 -0
  352. cuju/render/web/sw.js +235 -0
  353. cuju/render/web/vendor/fabric/LICENSE +16 -0
  354. cuju/render/web/vendor/fabric/fabric.min.mjs +1 -0
  355. cuju/render/web/vendor/lucide/LICENSE +43 -0
  356. cuju/render/web/vendor/lucide/icons.js +141 -0
  357. cuju/render/web/vendor/three/LICENSE +21 -0
  358. cuju/render/web/vendor/three/build/three.core.js +60586 -0
  359. cuju/render/web/vendor/three/build/three.module.js +19719 -0
  360. cuju/render/web/vendor/three/examples/jsm/loaders/GLTFLoader.js +4925 -0
  361. cuju/render/web/vendor/three/examples/jsm/postprocessing/EffectComposer.js +365 -0
  362. cuju/render/web/vendor/three/examples/jsm/postprocessing/MaskPass.js +195 -0
  363. cuju/render/web/vendor/three/examples/jsm/postprocessing/OutputPass.js +148 -0
  364. cuju/render/web/vendor/three/examples/jsm/postprocessing/Pass.js +191 -0
  365. cuju/render/web/vendor/three/examples/jsm/postprocessing/RenderPass.js +193 -0
  366. cuju/render/web/vendor/three/examples/jsm/postprocessing/ShaderPass.js +135 -0
  367. cuju/render/web/vendor/three/examples/jsm/postprocessing/UnrealBloomPass.js +541 -0
  368. cuju/render/web/vendor/three/examples/jsm/shaders/CopyShader.js +52 -0
  369. cuju/render/web/vendor/three/examples/jsm/shaders/LuminosityHighPassShader.js +68 -0
  370. cuju/render/web/vendor/three/examples/jsm/shaders/OutputShader.js +103 -0
  371. cuju/render/web/vendor/three/examples/jsm/utils/BufferGeometryUtils.js +1501 -0
  372. cuju/render/web/vendor/three/examples/jsm/utils/SkeletonUtils.js +496 -0
  373. cuju_render-0.1.0.dist-info/METADATA +116 -0
  374. cuju_render-0.1.0.dist-info/RECORD +382 -0
  375. cuju_render-0.1.0.dist-info/WHEEL +4 -0
  376. cuju_render-0.1.0.dist-info/licenses/LICENSE +202 -0
  377. cuju_render-0.1.0.dist-info/licenses/LICENSES/CC-BY-4.0.txt +396 -0
  378. cuju_render-0.1.0.dist-info/licenses/LICENSES/CC0-1.0.txt +127 -0
  379. cuju_render-0.1.0.dist-info/licenses/LICENSES/ISC.txt +16 -0
  380. cuju_render-0.1.0.dist-info/licenses/LICENSES/MIT.txt +24 -0
  381. cuju_render-0.1.0.dist-info/licenses/LICENSES/Unlicense.txt +13 -0
  382. cuju_render-0.1.0.dist-info/licenses/NOTICE +35 -0
@@ -0,0 +1,367 @@
1
+ // Sky.js from three.js r186, examples/jsm/objects/Sky.js, unchanged below this header.
2
+ // https://github.com/mrdoob/three.js/blob/r186/examples/jsm/objects/Sky.js
3
+ //
4
+ // The MIT License
5
+ //
6
+ // Copyright © 2010-2026 three.js authors
7
+ //
8
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ // of this software and associated documentation files (the "Software"), to deal
10
+ // in the Software without restriction, including without limitation the rights
11
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ // copies of the Software, and to permit persons to whom the Software is
13
+ // furnished to do so, subject to the following conditions:
14
+ //
15
+ // The above copyright notice and this permission notice shall be included in
16
+ // all copies or substantial portions of the Software.
17
+ //
18
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ // THE SOFTWARE.
25
+
26
+ import {
27
+ BackSide,
28
+ BoxGeometry,
29
+ Mesh,
30
+ ShaderMaterial,
31
+ UniformsUtils,
32
+ Vector3
33
+ } from 'three';
34
+
35
+ /**
36
+ * Represents a skydome for scene backgrounds. Based on [A Practical Analytic Model for Daylight](https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight)
37
+ * aka The Preetham Model, the de facto standard for analytical skydomes.
38
+ *
39
+ * Note that this class can only be used with {@link WebGLRenderer}.
40
+ * When using {@link WebGPURenderer}, use {@link SkyMesh}.
41
+ *
42
+ * More references:
43
+ *
44
+ * - {@link http://simonwallner.at/project/atmospheric-scattering/}
45
+ * - {@link http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR}
46
+ *
47
+ *
48
+ * ```js
49
+ * const sky = new Sky();
50
+ * sky.scale.setScalar( 10000 );
51
+ * scene.add( sky );
52
+ * ```
53
+ *
54
+ * It can be useful to hide the sun disc when generating an environment map to avoid artifacts
55
+ *
56
+ * ```js
57
+ * // disable before rendering environment map
58
+ * sky.material.uniforms.showSunDisc.value = false;
59
+ * // ...
60
+ * // re-enable before scene sky box rendering
61
+ * sky.material.uniforms.showSunDisc.value = true;
62
+ * ```
63
+ *
64
+ * @augments Mesh
65
+ * @three_import import { Sky } from 'three/addons/objects/Sky.js';
66
+ */
67
+ class Sky extends Mesh {
68
+
69
+ /**
70
+ * Constructs a new skydome.
71
+ */
72
+ constructor() {
73
+
74
+ const shader = Sky.SkyShader;
75
+
76
+ const material = new ShaderMaterial( {
77
+ name: shader.name,
78
+ uniforms: UniformsUtils.clone( shader.uniforms ),
79
+ vertexShader: shader.vertexShader,
80
+ fragmentShader: shader.fragmentShader,
81
+ side: BackSide,
82
+ depthWrite: false
83
+ } );
84
+
85
+ super( new BoxGeometry( 1, 1, 1 ), material );
86
+
87
+ /**
88
+ * This flag can be used for type testing.
89
+ *
90
+ * @type {boolean}
91
+ * @readonly
92
+ * @default true
93
+ */
94
+ this.isSky = true;
95
+
96
+ }
97
+
98
+ }
99
+
100
+ Sky.SkyShader = {
101
+
102
+ name: 'SkyShader',
103
+
104
+ uniforms: {
105
+ 'turbidity': { value: 2 },
106
+ 'rayleigh': { value: 1 },
107
+ 'mieCoefficient': { value: 0.005 },
108
+ 'mieDirectionalG': { value: 0.8 },
109
+ 'sunPosition': { value: new Vector3() },
110
+ 'cloudScale': { value: 0.0002 },
111
+ 'cloudSpeed': { value: 0.00002 },
112
+ 'cloudCoverage': { value: 0.4 },
113
+ 'cloudDensity': { value: 0.4 },
114
+ 'cloudElevation': { value: 0.5 },
115
+ 'showSunDisc': { value: 1 },
116
+ 'time': { value: 0.0 }
117
+ },
118
+
119
+ vertexShader: /* glsl */`
120
+ uniform vec3 sunPosition;
121
+ uniform float rayleigh;
122
+ uniform float turbidity;
123
+ uniform float mieCoefficient;
124
+
125
+ varying vec3 vWorldPosition;
126
+ varying vec3 vSunDirection;
127
+ varying float vSunfade;
128
+ varying vec3 vBetaR;
129
+ varying vec3 vBetaM;
130
+ varying float vSunE;
131
+
132
+ // constants for atmospheric scattering
133
+ const float e = 2.71828182845904523536028747135266249775724709369995957;
134
+ const float pi = 3.141592653589793238462643383279502884197169;
135
+
136
+ // wavelength of used primaries, according to preetham
137
+ const vec3 lambda = vec3( 680E-9, 550E-9, 450E-9 );
138
+ // this pre-calculation replaces older TotalRayleigh(vec3 lambda) function:
139
+ // (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn))
140
+ const vec3 totalRayleigh = vec3( 5.804542996261093E-6, 1.3562911419845635E-5, 3.0265902468824876E-5 );
141
+
142
+ // mie stuff
143
+ // K coefficient for the primaries
144
+ const float v = 4.0;
145
+ const vec3 K = vec3( 0.686, 0.678, 0.666 );
146
+ // MieConst = pi * pow( ( 2.0 * pi ) / lambda, vec3( v - 2.0 ) ) * K
147
+ const vec3 MieConst = vec3( 1.8399918514433978E14, 2.7798023919660528E14, 4.0790479543861094E14 );
148
+
149
+ // earth shadow hack
150
+ // cutoffAngle = pi / 1.95;
151
+ const float cutoffAngle = 1.6110731556870734;
152
+ const float steepness = 1.5;
153
+ const float EE = 1000.0;
154
+
155
+ float sunIntensity( float zenithAngleCos ) {
156
+ zenithAngleCos = clamp( zenithAngleCos, -1.0, 1.0 );
157
+ return EE * max( 0.0, 1.0 - pow( e, -( ( cutoffAngle - acos( zenithAngleCos ) ) / steepness ) ) );
158
+ }
159
+
160
+ vec3 totalMie( float T ) {
161
+ float c = ( 0.2 * T ) * 10E-18;
162
+ return 0.434 * c * MieConst;
163
+ }
164
+
165
+ void main() {
166
+
167
+ vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
168
+ vWorldPosition = worldPosition.xyz;
169
+
170
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
171
+ gl_Position.z = gl_Position.w; // set z to camera.far
172
+
173
+ vSunDirection = normalize( sunPosition );
174
+
175
+ vSunE = sunIntensity( vSunDirection.y );
176
+
177
+ vSunfade = 1.0 - clamp( 1.0 - exp( ( sunPosition.y / 450000.0 ) ), 0.0, 1.0 );
178
+
179
+ float rayleighCoefficient = rayleigh - ( 1.0 * ( 1.0 - vSunfade ) );
180
+
181
+ // extinction (absorption + out scattering)
182
+ // rayleigh coefficients
183
+ vBetaR = totalRayleigh * rayleighCoefficient;
184
+
185
+ // mie coefficients
186
+ vBetaM = totalMie( turbidity ) * mieCoefficient;
187
+
188
+ }`,
189
+
190
+ fragmentShader: /* glsl */`
191
+ varying vec3 vWorldPosition;
192
+ varying vec3 vSunDirection;
193
+ varying vec3 vBetaR;
194
+ varying vec3 vBetaM;
195
+ varying float vSunE;
196
+
197
+ uniform float mieDirectionalG;
198
+ uniform float cloudScale;
199
+ uniform float cloudSpeed;
200
+ uniform float cloudCoverage;
201
+ uniform float cloudDensity;
202
+ uniform float cloudElevation;
203
+ uniform float showSunDisc;
204
+ uniform float time;
205
+
206
+ // gradient at a lattice corner; sinless hash so every GPU produces the same clouds
207
+ vec2 gradient( vec2 i ) {
208
+ vec3 p = fract( i.xyx * vec3( 0.1031, 0.1030, 0.0973 ) );
209
+ p += dot( p, p.yzx + 33.33 );
210
+ return fract( ( p.xx + p.yz ) * p.zy ) * 2.0 - 1.0;
211
+ }
212
+
213
+ // 2D gradient noise: isotropic lobes like Perlin at value-noise cost
214
+ float noise( vec2 p ) {
215
+ vec2 i = floor( p );
216
+ vec2 f = fract( p );
217
+ vec2 u = f * f * f * ( f * ( f * 6.0 - 15.0 ) + 10.0 ); // quintic fade
218
+ float a = dot( gradient( i ), f );
219
+ float b = dot( gradient( i + vec2( 1.0, 0.0 ) ), f - vec2( 1.0, 0.0 ) );
220
+ float c = dot( gradient( i + vec2( 0.0, 1.0 ) ), f - vec2( 0.0, 1.0 ) );
221
+ float d = dot( gradient( i + vec2( 1.0, 1.0 ) ), f - vec2( 1.0, 1.0 ) );
222
+ return mix( mix( a, b, u.x ), mix( c, d, u.x ), u.y ) * 1.6; // ~[-1,1]
223
+ }
224
+
225
+ // fbm; per-octave drift makes clouds billow instead of scrolling as a rigid stamp
226
+ float fbm( vec2 p, float drift ) {
227
+ float result = 0.0;
228
+ float amplitude = 1.0;
229
+ for ( int i = 0; i < 4; i ++ ) {
230
+ result += amplitude * noise( p );
231
+ amplitude *= 0.5;
232
+ p = p * 2.0 + drift;
233
+ }
234
+ return result;
235
+ }
236
+
237
+ // constants for atmospheric scattering
238
+ const float pi = 3.141592653589793238462643383279502884197169;
239
+
240
+ const float n = 1.0003; // refractive index of air
241
+ const float N = 2.545E25; // number of molecules per unit volume for air at 288.15K and 1013mb (sea level -45 celsius)
242
+
243
+ // optical length at zenith for molecules
244
+ const float rayleighZenithLength = 8.4E3;
245
+ const float mieZenithLength = 1.25E3;
246
+ // 66 arc seconds -> degrees, and the cosine of that
247
+ const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;
248
+
249
+ // 3.0 / ( 16.0 * pi )
250
+ const float THREE_OVER_SIXTEENPI = 0.05968310365946075;
251
+ // 1.0 / ( 4.0 * pi )
252
+ const float ONE_OVER_FOURPI = 0.07957747154594767;
253
+
254
+ float rayleighPhase( float cosTheta ) {
255
+ return THREE_OVER_SIXTEENPI * ( 1.0 + pow( cosTheta, 2.0 ) );
256
+ }
257
+
258
+ float hgPhase( float cosTheta, float g ) {
259
+ float g2 = pow( g, 2.0 );
260
+ float inverse = 1.0 / pow( 1.0 - 2.0 * g * cosTheta + g2, 1.5 );
261
+ return ONE_OVER_FOURPI * ( ( 1.0 - g2 ) * inverse );
262
+ }
263
+
264
+ void main() {
265
+
266
+ vec3 direction = normalize( vWorldPosition - cameraPosition );
267
+
268
+ // optical length
269
+ // cutoff angle at 90 to avoid singularity in next formula.
270
+ float zenithAngle = acos( max( 0.0, direction.y ) );
271
+ float inverse = 1.0 / ( cos( zenithAngle ) + 0.15 * pow( 93.885 - ( ( zenithAngle * 180.0 ) / pi ), -1.253 ) );
272
+ float sR = rayleighZenithLength * inverse;
273
+ float sM = mieZenithLength * inverse;
274
+
275
+ // combined extinction factor
276
+ vec3 Fex = exp( -( vBetaR * sR + vBetaM * sM ) );
277
+
278
+ // in scattering
279
+ float cosTheta = dot( direction, vSunDirection );
280
+
281
+ float rPhase = rayleighPhase( cosTheta * 0.5 + 0.5 );
282
+ vec3 betaRTheta = vBetaR * rPhase;
283
+
284
+ float mPhase = hgPhase( cosTheta, mieDirectionalG );
285
+ vec3 betaMTheta = vBetaM * mPhase;
286
+
287
+ vec3 Lin = pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * ( 1.0 - Fex ), vec3( 1.5 ) );
288
+ Lin *= mix( vec3( 1.0 ), pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * Fex, vec3( 1.0 / 2.0 ) ), clamp( pow( 1.0 - vSunDirection.y, 5.0 ), 0.0, 1.0 ) );
289
+
290
+ // nightsky
291
+ float theta = acos( direction.y ); // elevation --> y-axis, [-pi/2, pi/2]
292
+ float phi = atan( direction.z, direction.x ); // azimuth --> x-axis [-pi/2, pi/2]
293
+ vec2 uv = vec2( phi, theta ) / vec2( 2.0 * pi, pi ) + vec2( 0.5, 0.0 );
294
+ vec3 L0 = vec3( 0.1 ) * Fex;
295
+
296
+ // composition + solar disc
297
+ float sundisc = clamp( ( cosTheta - sunAngularDiameterCos ) * 50000.0, 0.0, 1.0 ) * showSunDisc;
298
+ vec3 sundiscColor = ( 760.0 * sundisc ) * min( vSunE * Fex, 80.0 );
299
+
300
+ vec3 texColor = ( Lin + L0 ) * 0.04 + sundiscColor + vec3( 0.0, 0.0003, 0.00075 );
301
+
302
+ // Clouds
303
+ if ( direction.y > 0.0 && cloudCoverage > 0.0 ) {
304
+
305
+ // Project to cloud plane (higher elevation = clouds appear lower/closer)
306
+ float elevation = mix( 1.0, 0.1, cloudElevation );
307
+ vec2 cloudUV = direction.xz / ( direction.y * elevation );
308
+ cloudUV *= cloudScale;
309
+ cloudUV += time * cloudSpeed;
310
+
311
+ // Cloud density field
312
+ float evolve = time * cloudSpeed * 300.0;
313
+ float cloudNoise = clamp( fbm( cloudUV * 1000.0, evolve ) * 0.7 + 0.5, 0.0, 1.0 );
314
+
315
+ // Large-scale coverage variation: clear gaps next to dense banks
316
+ float region = noise( cloudUV * 300.0 ) * 0.37 + 0.5;
317
+ float cov = clamp( cloudCoverage + ( region - 0.5 ) * 0.6, 0.0, 1.0 );
318
+
319
+ // Carve clouds where noise rises above the coverage level
320
+ float threshold = 1.0 - cov;
321
+ float cloudMask = smoothstep( threshold, threshold + 0.3, cloudNoise );
322
+
323
+ // Fade clouds near horizon (adjusted by elevation)
324
+ float horizonFade = smoothstep( 0.0, 0.03 + 0.06 * cloudElevation, direction.y );
325
+ cloudMask *= horizonFade;
326
+
327
+ // Cloud lighting from the sky's own radiance
328
+ float dayFactor = smoothstep( -0.08, 0.3, vSunDirection.y );
329
+ vec3 sunColor = vSunE * Fex * 0.22 * 0.04; // 0.22 ~ albedo/pi, 0.04 = exposure; the aerial composite adds the eye-leg extinction
330
+ vec3 skyAmbient = Lin * 0.04 + vec3( 0.0, 0.0003, 0.00075 );
331
+
332
+ // Beer-powder self-shadow from the sampled density
333
+ float depth = max( 0.0, cloudNoise - threshold );
334
+ float beer = exp( depth * -4.0 );
335
+ float powder = 1.0 - beer * beer; // beer*beer == exp(-8*depth)
336
+ float shade = mix( 0.45, 1.0, clamp( beer * powder * 2.6, 0.0, 1.0 ) ); // 2.6 = 1/0.385, normalizes beer*powder peak to 1
337
+
338
+ // Henyey-Greenstein forward lobe ( g = 0.7 ): silver lining on rims toward the sun
339
+ float silver = clamp( 0.51 / pow( 1.49 - cosTheta * 1.4, 1.5 ), 0.0, 3.0 ); // 0.51=1-g^2, 1.49=1+g^2, 1.4=2g
340
+ float edge = cloudMask * ( 1.0 - cloudMask ) * 4.0;
341
+
342
+ vec3 cloudColor = skyAmbient + sunColor * shade;
343
+ cloudColor += sunColor * silver * edge * 0.6;
344
+ cloudColor *= max( dayFactor, 0.03 );
345
+
346
+ // Cloud opacity via Beer's law: density sets how solid the clouds get
347
+ float alpha = ( 1.0 - exp( depth * cloudDensity * -12.0 ) ) * horizonFade;
348
+
349
+ // Occlude the sun disc/glow behind opaque cloud
350
+ texColor -= L0 * 0.04 * alpha;
351
+
352
+ // Composite through the atmosphere so distant clouds dissolve into haze
353
+ vec3 cloudAerial = mix( texColor, cloudColor, Fex );
354
+ texColor = mix( texColor, cloudAerial, alpha );
355
+
356
+ }
357
+
358
+ gl_FragColor = vec4( texColor, 1.0 );
359
+
360
+ #include <tonemapping_fragment>
361
+ #include <colorspace_fragment>
362
+
363
+ }`
364
+
365
+ };
366
+
367
+ export { Sky };
@@ -0,0 +1,264 @@
1
+ // Copyright 2026 The cuju Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // Rain, snow and splashes. Every particle is one instance of a small quad whose place comes from
5
+ // its seed and the time in the vertex shader, so the processor only sets a few uniforms a frame.
6
+ // The drops are anchored to the world and wrap around a box that follows the camera, so they
7
+ // never swim with it. Quality sets how many there are, the low quality draws none.
8
+
9
+ import * as THREE from 'three';
10
+ import { FULL_HALF_H, FULL_HALF_W } from './pitch.js';
11
+
12
+ const COUNTS = {
13
+ low: { rain: 0, snow: 0, splash: 0 },
14
+ medium: { rain: 6000, snow: 4000, splash: 900 },
15
+ high: { rain: 16000, snow: 9000, splash: 2400 },
16
+ };
17
+ // The box of drops around the camera, its half size in meters.
18
+ const RAIN_HALF = new THREE.Vector3(36, 22, 36);
19
+ const SNOW_HALF = new THREE.Vector3(30, 18, 30);
20
+
21
+ const COMMON = `
22
+ uniform float uTime;
23
+ uniform vec3 uCenter;
24
+ uniform vec3 uHalf;
25
+ uniform vec3 uVel;
26
+ attribute vec4 seed;
27
+ varying vec2 vUv;
28
+ varying float vFade;
29
+ vec3 cjWrap(vec3 p) {
30
+ vec3 rel = mod(p - uCenter + uHalf, uHalf * 2.0) - uHalf;
31
+ vFade = 1.0 - smoothstep(0.75, 1.0, length(rel.xz) / uHalf.x);
32
+ vFade *= 1.0 - smoothstep(0.8, 1.0, abs(rel.y) / uHalf.y);
33
+ return uCenter + rel;
34
+ }
35
+ `;
36
+
37
+ const RAIN_VERTEX = `${COMMON}
38
+ uniform float uLen;
39
+ uniform float uWidth;
40
+ void main() {
41
+ float speed = 0.85 + 0.3 * seed.w;
42
+ vec3 head = cjWrap(seed.xyz * uHalf * 2.0 + uVel * speed * uTime);
43
+ vec3 dir = normalize(uVel);
44
+ vec3 p = head - dir * uLen * speed * position.y;
45
+ vec3 toCam = cameraPosition - p;
46
+ float dist = length(toCam);
47
+ // Far drops widen to about a pixel and fade to match, so they shimmer rather than flicker.
48
+ float width = max(uWidth, dist * 0.0022);
49
+ vFade *= uWidth / width * 0.5 + 0.5;
50
+ vFade *= step(0.0, p.y) * smoothstep(0.6, 3.0, dist);
51
+ p += normalize(cross(dir, toCam)) * width * position.x;
52
+ vUv = position.xy;
53
+ gl_Position = projectionMatrix * viewMatrix * vec4(p, 1.0);
54
+ }`;
55
+
56
+ const SNOW_VERTEX = `${COMMON}
57
+ uniform float uSize;
58
+ void main() {
59
+ float t = uTime * (0.7 + 0.6 * seed.w);
60
+ vec3 sway = vec3(sin(t * 1.3 + seed.x * 40.0), 0.0, cos(t * 1.1 + seed.z * 40.0)) * 0.5;
61
+ vec3 head = cjWrap(seed.xyz * uHalf * 2.0 + uVel * t + sway);
62
+ vec3 right = vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]);
63
+ vec3 up = vec3(viewMatrix[0][1], viewMatrix[1][1], viewMatrix[2][1]);
64
+ float dist = length(cameraPosition - head);
65
+ float size = max(uSize * (0.6 + 0.8 * seed.w), dist * 0.0016);
66
+ vFade *= step(0.0, head.y) * smoothstep(0.4, 2.0, dist) * min(1.0, uSize * 1.5 / size + 0.25);
67
+ vec3 p = head + (right * position.x + up * (position.y * 2.0 - 1.0)) * size;
68
+ vUv = vec2(position.x, position.y * 2.0 - 1.0);
69
+ gl_Position = projectionMatrix * viewMatrix * vec4(p, 1.0);
70
+ }`;
71
+
72
+ // Rings spreading on the ground where drops land, each at a new place every cycle.
73
+ const SPLASH_VERTEX = `
74
+ uniform float uTime;
75
+ uniform vec2 uArea;
76
+ attribute vec4 seed;
77
+ varying vec2 vUv;
78
+ varying float vFade;
79
+ float cjHash(vec2 p) {
80
+ p = fract(p * vec2(0.1031, 0.1030));
81
+ p += dot(p, p.yx + 33.33);
82
+ return fract((p.x + p.y) * p.x);
83
+ }
84
+ void main() {
85
+ float period = 0.45 + 0.35 * seed.w;
86
+ float c = uTime / period + seed.z * 7.0;
87
+ float cycle = floor(c);
88
+ float phase = fract(c);
89
+ vec2 at = (vec2(cjHash(seed.xy * 91.0 + cycle), cjHash(seed.yx * 57.0 + cycle * 1.7)) * 2.0 - 1.0) * uArea;
90
+ float r = 0.05 + 0.22 * phase;
91
+ vec3 p = vec3(at.x + position.x * r, 0.03, at.y + position.y * r);
92
+ vUv = position.xy;
93
+ vFade = 1.0 - phase;
94
+ gl_Position = projectionMatrix * viewMatrix * vec4(p, 1.0);
95
+ }`;
96
+
97
+ const FRAGMENT_HEAD = `
98
+ uniform vec3 uColor;
99
+ uniform float uOpacity;
100
+ varying vec2 vUv;
101
+ varying float vFade;
102
+ `;
103
+ const FRAGMENT_TAIL = `
104
+ if (a < 0.004) {
105
+ discard;
106
+ }
107
+ gl_FragColor = vec4(uColor, a);
108
+ #include <tonemapping_fragment>
109
+ #include <colorspace_fragment>
110
+ }`;
111
+
112
+ const RAIN_FRAGMENT = `${FRAGMENT_HEAD}
113
+ void main() {
114
+ float a = (1.0 - abs(vUv.x)) * (1.0 - 0.7 * vUv.y) * vFade * uOpacity;
115
+ ${FRAGMENT_TAIL}`;
116
+
117
+ const SNOW_FRAGMENT = `${FRAGMENT_HEAD}
118
+ void main() {
119
+ float a = smoothstep(1.0, 0.3, length(vUv)) * vFade * uOpacity;
120
+ ${FRAGMENT_TAIL}`;
121
+
122
+ const SPLASH_FRAGMENT = `${FRAGMENT_HEAD}
123
+ void main() {
124
+ float d = length(vUv);
125
+ float a = smoothstep(0.65, 0.85, d) * smoothstep(1.0, 0.88, d) * vFade * uOpacity;
126
+ ${FRAGMENT_TAIL}`;
127
+
128
+ function rand(seed) {
129
+ let s = seed >>> 0;
130
+ return () => {
131
+ s = (s + 0x6d2b79f5) >>> 0;
132
+ let t = s;
133
+ t = Math.imul(t ^ (t >>> 15), t | 1);
134
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
135
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
136
+ };
137
+ }
138
+
139
+ function particles(count, quad, vertexShader, fragmentShader, uniforms, seedValue) {
140
+ const geometry = new THREE.InstancedBufferGeometry();
141
+ geometry.setAttribute('position', new THREE.Float32BufferAttribute(quad, 3));
142
+ geometry.setIndex([0, 1, 2, 0, 2, 3]);
143
+ const seeds = new Float32Array(count * 4);
144
+ const r = rand(seedValue);
145
+ for (let i = 0; i < seeds.length; i++) {
146
+ seeds[i] = r();
147
+ }
148
+ geometry.setAttribute('seed', new THREE.InstancedBufferAttribute(seeds, 4));
149
+ geometry.instanceCount = 0;
150
+ const material = new THREE.ShaderMaterial({
151
+ uniforms, vertexShader, fragmentShader, transparent: true, depthWrite: false, side: THREE.DoubleSide,
152
+ });
153
+ const mesh = new THREE.Mesh(geometry, material);
154
+ mesh.frustumCulled = false;
155
+ mesh.visible = false;
156
+ mesh.renderOrder = 5;
157
+ return mesh;
158
+ }
159
+
160
+ export class Weather {
161
+ constructor(scene) {
162
+ this.group = new THREE.Group();
163
+ scene.add(this.group);
164
+ this.quality = 'medium';
165
+ this.state = { rain: 0, snow: 0, wind: 0 };
166
+ this.rainU = {
167
+ uTime: { value: 0 }, uCenter: { value: new THREE.Vector3() }, uHalf: { value: RAIN_HALF.clone() },
168
+ uVel: { value: new THREE.Vector3(0, -11, 0) }, uLen: { value: 0.9 }, uWidth: { value: 0.012 },
169
+ uColor: { value: new THREE.Color(0xc8d2dc) }, uOpacity: { value: 0.35 },
170
+ };
171
+ this.snowU = {
172
+ uTime: { value: 0 }, uCenter: { value: new THREE.Vector3() }, uHalf: { value: SNOW_HALF.clone() },
173
+ uVel: { value: new THREE.Vector3(0, -1.2, 0) }, uSize: { value: 0.035 },
174
+ uColor: { value: new THREE.Color(0xffffff) }, uOpacity: { value: 0.85 },
175
+ };
176
+ this.splashU = {
177
+ uTime: { value: 0 }, uArea: { value: new THREE.Vector2(FULL_HALF_W + 2, FULL_HALF_H + 2) },
178
+ uColor: { value: new THREE.Color(0xdfe6ee) }, uOpacity: { value: 0.5 },
179
+ };
180
+ this.build();
181
+ }
182
+
183
+ build() {
184
+ this.disposeMeshes();
185
+ const c = COUNTS[this.quality] || COUNTS.medium;
186
+ this.max = c;
187
+ this.rain = particles(c.rain, [-1, 0, 0, 1, 0, 0, 1, 1, 0, -1, 1, 0], RAIN_VERTEX, RAIN_FRAGMENT, this.rainU, 7);
188
+ this.snow = particles(c.snow, [-1, 0, 0, 1, 0, 0, 1, 1, 0, -1, 1, 0], SNOW_VERTEX, SNOW_FRAGMENT, this.snowU, 11);
189
+ this.splash = particles(c.splash, [-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0], SPLASH_VERTEX, SPLASH_FRAGMENT, this.splashU, 13);
190
+ this.group.add(this.rain, this.snow, this.splash);
191
+ this.applyCounts();
192
+ }
193
+
194
+ setQuality(quality) {
195
+ if (quality === this.quality && this.rain) {
196
+ return;
197
+ }
198
+ this.quality = quality;
199
+ this.build();
200
+ }
201
+
202
+ // Takes the lighting of the hour and weather, see lightingAt.
203
+ set(L) {
204
+ this.state = { rain: L.rain, snow: L.snow, wind: L.wind };
205
+ const wind = L.wind;
206
+ // Wind blows along the pitch from the right end, and a little towards the camera.
207
+ const gust = new THREE.Vector3(-1, 0, 0.35).normalize();
208
+ this.rainU.uVel.value.set(0, -11 - 3 * L.rain, 0).addScaledVector(gust, 9 * wind);
209
+ this.snowU.uVel.value.set(0, -1.1, 0).addScaledVector(gust, 3.5 * wind);
210
+ // Drops catch the light around them, the floodlights at night.
211
+ const light = Math.min(1.2, 0.25 + 0.45 * L.hemiIntensity + 0.15 * L.lightIntensity + 0.8 * L.flood);
212
+ this.rainU.uColor.value.setRGB(0.78, 0.82, 0.88).multiplyScalar(light);
213
+ this.rainU.uOpacity.value = 0.3 + 0.25 * L.rain;
214
+ this.snowU.uColor.value.setRGB(0.95, 0.96, 1.0).multiplyScalar(Math.min(1.1, 0.35 + 0.5 * L.hemiIntensity + 0.15 * L.lightIntensity + 0.7 * L.flood));
215
+ this.splashU.uColor.value.copy(this.rainU.uColor.value);
216
+ this.applyCounts();
217
+ }
218
+
219
+ applyCounts() {
220
+ const c = this.max;
221
+ const s = this.state;
222
+ this.rain.geometry.instanceCount = Math.round(c.rain * Math.min(1, s.rain));
223
+ this.snow.geometry.instanceCount = Math.round(c.snow * Math.min(1, s.snow));
224
+ this.splash.geometry.instanceCount = Math.round(c.splash * Math.min(1, s.rain));
225
+ this.rain.visible = this.rain.geometry.instanceCount > 0;
226
+ this.snow.visible = this.snow.geometry.instanceCount > 0;
227
+ this.splash.visible = this.splash.geometry.instanceCount > 0;
228
+ }
229
+
230
+ // The boxes sit a little ahead of the camera, where most of what it sees is.
231
+ update(seconds, camera) {
232
+ const t = seconds % 3600;
233
+ this.rainU.uTime.value = t;
234
+ this.snowU.uTime.value = t;
235
+ this.splashU.uTime.value = t;
236
+ if (!this.rain.visible && !this.snow.visible) {
237
+ return;
238
+ }
239
+ const ahead = camera.getWorldDirection(this.ahead || (this.ahead = new THREE.Vector3()));
240
+ ahead.y = 0;
241
+ if (ahead.lengthSq() > 1e-6) {
242
+ ahead.normalize();
243
+ }
244
+ this.rainU.uCenter.value.copy(camera.position).addScaledVector(ahead, RAIN_HALF.x * 0.55);
245
+ this.rainU.uCenter.value.y = Math.max(RAIN_HALF.y - 2, camera.position.y - 4);
246
+ this.snowU.uCenter.value.copy(camera.position).addScaledVector(ahead, SNOW_HALF.x * 0.55);
247
+ this.snowU.uCenter.value.y = Math.max(SNOW_HALF.y - 2, camera.position.y - 4);
248
+ }
249
+
250
+ disposeMeshes() {
251
+ for (const mesh of [this.rain, this.snow, this.splash]) {
252
+ if (mesh) {
253
+ mesh.removeFromParent();
254
+ mesh.geometry.dispose();
255
+ mesh.material.dispose();
256
+ }
257
+ }
258
+ }
259
+
260
+ dispose() {
261
+ this.disposeMeshes();
262
+ this.group.removeFromParent();
263
+ }
264
+ }