@rosetears/aili-pi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +109 -0
  3. package/THIRD_PARTY_NOTICES.md +64 -0
  4. package/extensions/index.ts +6 -0
  5. package/install.sh +5 -0
  6. package/manifests/adapter-evidence.json +45 -0
  7. package/manifests/capabilities.json +124 -0
  8. package/manifests/live-verification.json +26 -0
  9. package/manifests/provenance.json +71 -0
  10. package/manifests/roles.json +474 -0
  11. package/manifests/sbom.json +7797 -0
  12. package/manifests/skill-compatibility.json +8100 -0
  13. package/manifests/subagent-provenance.json +37 -0
  14. package/package.json +91 -0
  15. package/prompts/build.md +8 -0
  16. package/prompts/define.md +8 -0
  17. package/prompts/ideate.md +8 -0
  18. package/prompts/local-review.md +8 -0
  19. package/prompts/ship.md +8 -0
  20. package/roles/agent-evaluator.md +47 -0
  21. package/roles/ai-regression-scout.md +47 -0
  22. package/roles/browser-qa-runner.md +47 -0
  23. package/roles/code-reviewer.md +47 -0
  24. package/roles/code-scout.md +47 -0
  25. package/roles/convergence-reviewer.md +55 -0
  26. package/roles/doc-researcher.md +47 -0
  27. package/roles/e2e-artifact-runner.md +47 -0
  28. package/roles/implementer.md +47 -0
  29. package/roles/opensource-sanitizer.md +47 -0
  30. package/roles/plan-auditor.md +47 -0
  31. package/roles/pr-test-analyzer.md +47 -0
  32. package/roles/security-auditor.md +47 -0
  33. package/roles/silent-failure-reviewer.md +47 -0
  34. package/roles/spec-miner.md +47 -0
  35. package/roles/test-coverage-reviewer.md +47 -0
  36. package/roles/test-engineer.md +48 -0
  37. package/roles/web-performance-auditor.md +47 -0
  38. package/roles/web-researcher.md +47 -0
  39. package/scripts/apply-adapter-evidence.ts +73 -0
  40. package/scripts/bootstrap.sh +180 -0
  41. package/scripts/generate-provenance.ts +143 -0
  42. package/scripts/local-package-e2e.ts +51 -0
  43. package/scripts/sync-roles.ts +213 -0
  44. package/scripts/sync-skills.ts +356 -0
  45. package/scripts/validate-runtime.ts +11 -0
  46. package/skills/academic-paper-review/SKILL.md +81 -0
  47. package/skills/agents-md-initialization/SKILL.md +121 -0
  48. package/skills/agents-md-initialization/references/agents-template.md +83 -0
  49. package/skills/agents-md-initialization/references/agents_md.py +215 -0
  50. package/skills/ai-regression-scout/SKILL.md +24 -0
  51. package/skills/aili-delivery-flow/SKILL.md +125 -0
  52. package/skills/aili-delivery-flow/references/artifact-contracts.md +138 -0
  53. package/skills/aili-delivery-flow/references/backend-routing.md +40 -0
  54. package/skills/aili-delivery-flow/references/build-execution-loop.md +113 -0
  55. package/skills/aili-delivery-flow/references/build-goal-mode.md +3 -0
  56. package/skills/aili-delivery-flow/references/direct-vs-delegated-work.md +38 -0
  57. package/skills/aili-delivery-flow/references/implementation-packages.md +54 -0
  58. package/skills/aili-delivery-flow/references/lifecycle.md +127 -0
  59. package/skills/aili-delivery-flow/references/protocols/acceptance-test-plan.md +18 -0
  60. package/skills/aili-delivery-flow/references/protocols/alignment-questionnaire.md +10 -0
  61. package/skills/aili-delivery-flow/references/protocols/closeout-report.md +101 -0
  62. package/skills/aili-delivery-flow/references/protocols/compact-evidence-pack.md +46 -0
  63. package/skills/aili-delivery-flow/references/protocols/idea-brief.md +10 -0
  64. package/skills/aili-delivery-flow/references/protocols/implementation-package.md +53 -0
  65. package/skills/aili-delivery-flow/references/protocols/research-evidence-pack.md +19 -0
  66. package/skills/aili-delivery-flow/references/protocols/review-report.md +7 -0
  67. package/skills/aili-delivery-flow/references/protocols/spec-draft.md +12 -0
  68. package/skills/aili-delivery-flow/references/protocols/subagent-result.md +60 -0
  69. package/skills/aili-delivery-flow/references/protocols/subagent-task-packet.md +29 -0
  70. package/skills/aili-delivery-flow/references/protocols/worktree-context.md +109 -0
  71. package/skills/aili-delivery-flow/references/questionnaire-policy.md +62 -0
  72. package/skills/aili-delivery-flow/references/review-repair-loop.md +16 -0
  73. package/skills/aili-delivery-flow/references/test-document-policy.md +35 -0
  74. package/skills/android-native-dev/SKILL.md +722 -0
  75. package/skills/android-native-dev/references/accessibility.md +209 -0
  76. package/skills/android-native-dev/references/adaptive-screens.md +231 -0
  77. package/skills/android-native-dev/references/design-style-guide.md +365 -0
  78. package/skills/android-native-dev/references/functional-requirements.md +229 -0
  79. package/skills/android-native-dev/references/motion-system.md +203 -0
  80. package/skills/android-native-dev/references/performance-stability.md +223 -0
  81. package/skills/android-native-dev/references/privacy-security.md +244 -0
  82. package/skills/android-native-dev/references/testing.md +554 -0
  83. package/skills/android-native-dev/references/visual-design.md +246 -0
  84. package/skills/api-and-interface-design/SKILL.md +318 -0
  85. package/skills/browser-qa/SKILL.md +32 -0
  86. package/skills/browser-testing-with-devtools/SKILL.md +323 -0
  87. package/skills/build-failure-repair/SKILL.md +49 -0
  88. package/skills/chart-visualization/SKILL.md +73 -0
  89. package/skills/ci-cd-and-automation/SKILL.md +353 -0
  90. package/skills/code-review-and-quality/SKILL.md +375 -0
  91. package/skills/code-review-quality-gates/SKILL.md +132 -0
  92. package/skills/code-simplification/SKILL.md +371 -0
  93. package/skills/comment-accuracy-review/SKILL.md +37 -0
  94. package/skills/consulting-analysis/SKILL.md +69 -0
  95. package/skills/context-engineering/SKILL.md +375 -0
  96. package/skills/coverage-review/SKILL.md +24 -0
  97. package/skills/data-analysis/SKILL.md +74 -0
  98. package/skills/deprecation-and-migration/SKILL.md +222 -0
  99. package/skills/documentation-and-adrs/SKILL.md +330 -0
  100. package/skills/e2e-artifact-handling/SKILL.md +30 -0
  101. package/skills/evidence-scoped-retrospective/SKILL.md +156 -0
  102. package/skills/explain-by-allegory/SKILL.md +99 -0
  103. package/skills/flutter-dev/SKILL.md +162 -0
  104. package/skills/flutter-dev/references/animations.md +497 -0
  105. package/skills/flutter-dev/references/bloc-state.md +281 -0
  106. package/skills/flutter-dev/references/forms.md +656 -0
  107. package/skills/flutter-dev/references/gorouter-navigation.md +257 -0
  108. package/skills/flutter-dev/references/localization.md +510 -0
  109. package/skills/flutter-dev/references/networking.md +566 -0
  110. package/skills/flutter-dev/references/performance.md +305 -0
  111. package/skills/flutter-dev/references/platform-specific.md +417 -0
  112. package/skills/flutter-dev/references/project-structure.md +273 -0
  113. package/skills/flutter-dev/references/riverpod-state.md +232 -0
  114. package/skills/flutter-dev/references/testing.md +364 -0
  115. package/skills/flutter-dev/references/widget-patterns.md +233 -0
  116. package/skills/frontend-dev/SKILL.md +468 -0
  117. package/skills/frontend-dev/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  118. package/skills/frontend-dev/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  119. package/skills/frontend-dev/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  120. package/skills/frontend-dev/canvas-fonts/BigShoulders-OFL.txt +93 -0
  121. package/skills/frontend-dev/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  122. package/skills/frontend-dev/canvas-fonts/Boldonse-OFL.txt +93 -0
  123. package/skills/frontend-dev/canvas-fonts/Boldonse-Regular.ttf +0 -0
  124. package/skills/frontend-dev/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  125. package/skills/frontend-dev/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  126. package/skills/frontend-dev/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  127. package/skills/frontend-dev/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  128. package/skills/frontend-dev/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  129. package/skills/frontend-dev/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  130. package/skills/frontend-dev/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  131. package/skills/frontend-dev/canvas-fonts/DMMono-OFL.txt +93 -0
  132. package/skills/frontend-dev/canvas-fonts/DMMono-Regular.ttf +0 -0
  133. package/skills/frontend-dev/canvas-fonts/EricaOne-OFL.txt +94 -0
  134. package/skills/frontend-dev/canvas-fonts/EricaOne-Regular.ttf +0 -0
  135. package/skills/frontend-dev/canvas-fonts/GeistMono-Bold.ttf +0 -0
  136. package/skills/frontend-dev/canvas-fonts/GeistMono-OFL.txt +93 -0
  137. package/skills/frontend-dev/canvas-fonts/GeistMono-Regular.ttf +0 -0
  138. package/skills/frontend-dev/canvas-fonts/Gloock-OFL.txt +93 -0
  139. package/skills/frontend-dev/canvas-fonts/Gloock-Regular.ttf +0 -0
  140. package/skills/frontend-dev/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  141. package/skills/frontend-dev/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  142. package/skills/frontend-dev/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  143. package/skills/frontend-dev/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  144. package/skills/frontend-dev/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  145. package/skills/frontend-dev/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  146. package/skills/frontend-dev/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  147. package/skills/frontend-dev/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  148. package/skills/frontend-dev/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  149. package/skills/frontend-dev/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  150. package/skills/frontend-dev/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  151. package/skills/frontend-dev/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  152. package/skills/frontend-dev/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  153. package/skills/frontend-dev/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  154. package/skills/frontend-dev/canvas-fonts/Italiana-OFL.txt +93 -0
  155. package/skills/frontend-dev/canvas-fonts/Italiana-Regular.ttf +0 -0
  156. package/skills/frontend-dev/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  157. package/skills/frontend-dev/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  158. package/skills/frontend-dev/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  159. package/skills/frontend-dev/canvas-fonts/Jura-Light.ttf +0 -0
  160. package/skills/frontend-dev/canvas-fonts/Jura-Medium.ttf +0 -0
  161. package/skills/frontend-dev/canvas-fonts/Jura-OFL.txt +93 -0
  162. package/skills/frontend-dev/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  163. package/skills/frontend-dev/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  164. package/skills/frontend-dev/canvas-fonts/Lora-Bold.ttf +0 -0
  165. package/skills/frontend-dev/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  166. package/skills/frontend-dev/canvas-fonts/Lora-Italic.ttf +0 -0
  167. package/skills/frontend-dev/canvas-fonts/Lora-OFL.txt +93 -0
  168. package/skills/frontend-dev/canvas-fonts/Lora-Regular.ttf +0 -0
  169. package/skills/frontend-dev/canvas-fonts/NationalPark-Bold.ttf +0 -0
  170. package/skills/frontend-dev/canvas-fonts/NationalPark-OFL.txt +93 -0
  171. package/skills/frontend-dev/canvas-fonts/NationalPark-Regular.ttf +0 -0
  172. package/skills/frontend-dev/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  173. package/skills/frontend-dev/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  174. package/skills/frontend-dev/canvas-fonts/Outfit-Bold.ttf +0 -0
  175. package/skills/frontend-dev/canvas-fonts/Outfit-OFL.txt +93 -0
  176. package/skills/frontend-dev/canvas-fonts/Outfit-Regular.ttf +0 -0
  177. package/skills/frontend-dev/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  178. package/skills/frontend-dev/canvas-fonts/PixelifySans-OFL.txt +93 -0
  179. package/skills/frontend-dev/canvas-fonts/PoiretOne-OFL.txt +93 -0
  180. package/skills/frontend-dev/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  181. package/skills/frontend-dev/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  182. package/skills/frontend-dev/canvas-fonts/RedHatMono-OFL.txt +93 -0
  183. package/skills/frontend-dev/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  184. package/skills/frontend-dev/canvas-fonts/Silkscreen-OFL.txt +93 -0
  185. package/skills/frontend-dev/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  186. package/skills/frontend-dev/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  187. package/skills/frontend-dev/canvas-fonts/SmoochSans-OFL.txt +93 -0
  188. package/skills/frontend-dev/canvas-fonts/Tektur-Medium.ttf +0 -0
  189. package/skills/frontend-dev/canvas-fonts/Tektur-OFL.txt +93 -0
  190. package/skills/frontend-dev/canvas-fonts/Tektur-Regular.ttf +0 -0
  191. package/skills/frontend-dev/canvas-fonts/WorkSans-Bold.ttf +0 -0
  192. package/skills/frontend-dev/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  193. package/skills/frontend-dev/canvas-fonts/WorkSans-Italic.ttf +0 -0
  194. package/skills/frontend-dev/canvas-fonts/WorkSans-OFL.txt +93 -0
  195. package/skills/frontend-dev/canvas-fonts/WorkSans-Regular.ttf +0 -0
  196. package/skills/frontend-dev/canvas-fonts/YoungSerif-OFL.txt +93 -0
  197. package/skills/frontend-dev/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  198. package/skills/frontend-dev/references/asset-prompt-guide.md +43 -0
  199. package/skills/frontend-dev/references/env-setup.md +33 -0
  200. package/skills/frontend-dev/references/minimax-cli-reference.md +133 -0
  201. package/skills/frontend-dev/references/minimax-image-guide.md +65 -0
  202. package/skills/frontend-dev/references/minimax-music-guide.md +216 -0
  203. package/skills/frontend-dev/references/minimax-tts-guide.md +78 -0
  204. package/skills/frontend-dev/references/minimax-video-guide.md +82 -0
  205. package/skills/frontend-dev/references/minimax-voice-catalog.md +685 -0
  206. package/skills/frontend-dev/references/motion-recipes.md +407 -0
  207. package/skills/frontend-dev/references/troubleshooting.md +85 -0
  208. package/skills/frontend-dev/scripts/minimax_image.py +137 -0
  209. package/skills/frontend-dev/scripts/minimax_music.py +157 -0
  210. package/skills/frontend-dev/scripts/minimax_tts.py +127 -0
  211. package/skills/frontend-dev/scripts/minimax_video.py +187 -0
  212. package/skills/frontend-dev/templates/generator_template.js +223 -0
  213. package/skills/frontend-dev/templates/viewer.html +599 -0
  214. package/skills/frontend-ui-engineering/SKILL.md +367 -0
  215. package/skills/fullstack-dev/SKILL.md +819 -0
  216. package/skills/fullstack-dev/references/api-design.md +444 -0
  217. package/skills/fullstack-dev/references/auth-flow.md +165 -0
  218. package/skills/fullstack-dev/references/db-schema.md +706 -0
  219. package/skills/fullstack-dev/references/django-best-practices.md +466 -0
  220. package/skills/fullstack-dev/references/environment-management.md +78 -0
  221. package/skills/fullstack-dev/references/release-checklist.md +278 -0
  222. package/skills/fullstack-dev/references/technology-selection.md +254 -0
  223. package/skills/fullstack-dev/references/testing-strategy.md +404 -0
  224. package/skills/git-workflow-and-versioning/SKILL.md +446 -0
  225. package/skills/github-evidence-triage/SKILL.md +115 -0
  226. package/skills/harness-evolution/SKILL.md +59 -0
  227. package/skills/harness-evolution/references/activation-matrix.md +13 -0
  228. package/skills/harness-evolution/references/approval-policy.md +20 -0
  229. package/skills/harness-evolution/references/change-report-template.md +33 -0
  230. package/skills/harness-evolution/references/component-taxonomy.md +19 -0
  231. package/skills/harness-evolution/references/verdict-policy.md +13 -0
  232. package/skills/harness-issue-triage/SKILL.md +72 -0
  233. package/skills/harness-issue-triage/references/component-diagnosis.md +25 -0
  234. package/skills/harness-issue-triage/references/triage-report-template.md +34 -0
  235. package/skills/harness-optimization-audit/SKILL.md +125 -0
  236. package/skills/idea-refine/SKILL.md +191 -0
  237. package/skills/idea-refine/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/LICENSE +21 -0
  238. package/skills/idea-refine/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/NOTICE.md +9 -0
  239. package/skills/idea-refine/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/idea-refine/SKILL.upstream.md +178 -0
  240. package/skills/idea-refine/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/idea-refine/examples.md +238 -0
  241. package/skills/idea-refine/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/idea-refine/frameworks.md +99 -0
  242. package/skills/idea-refine/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/idea-refine/refinement-criteria.md +113 -0
  243. package/skills/idea-refine/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/idea-refine/scripts/idea-refine.upstream.sh +15 -0
  244. package/skills/incremental-implementation/SKILL.md +252 -0
  245. package/skills/ios-application-dev/SKILL.md +212 -0
  246. package/skills/ios-application-dev/references/accessibility.md +259 -0
  247. package/skills/ios-application-dev/references/graphics-animation.md +350 -0
  248. package/skills/ios-application-dev/references/layout-system.md +199 -0
  249. package/skills/ios-application-dev/references/metal-shader.md +178 -0
  250. package/skills/ios-application-dev/references/navigation-patterns.md +175 -0
  251. package/skills/ios-application-dev/references/swift-coding-standards.md +757 -0
  252. package/skills/ios-application-dev/references/swiftui-design-guidelines.md +1167 -0
  253. package/skills/ios-application-dev/references/system-integration.md +401 -0
  254. package/skills/ios-application-dev/references/uikit-components.md +297 -0
  255. package/skills/local-review-gate/SKILL.md +207 -0
  256. package/skills/local-review-gate/references/addyosmani-code-review-rubric.md +33 -0
  257. package/skills/local-review-gate/references/codex-github-compatibility.md +26 -0
  258. package/skills/local-review-gate/references/ecc-code-review-adaptation.md +40 -0
  259. package/skills/local-review-gate/references/graphify-local-review.md +33 -0
  260. package/skills/local-review-gate/references/orchestration-adaptation.md +51 -0
  261. package/skills/local-review-gate/references/review-repair-lane-adaptation.md +46 -0
  262. package/skills/local-review-gate/references/upstream-provenance.md +61 -0
  263. package/skills/mature-project-pattern-research/SKILL.md +155 -0
  264. package/skills/mature-project-pattern-research/references/research-rubric.md +45 -0
  265. package/skills/minimax-docx/LICENSE +21 -0
  266. package/skills/minimax-docx/SKILL.md +273 -0
  267. package/skills/minimax-docx/assets/styles/academic_styles.xml +250 -0
  268. package/skills/minimax-docx/assets/styles/corporate_styles.xml +284 -0
  269. package/skills/minimax-docx/assets/styles/default_styles.xml +449 -0
  270. package/skills/minimax-docx/assets/xsd/aesthetic-rules.xsd +470 -0
  271. package/skills/minimax-docx/assets/xsd/business-rules.xsd +130 -0
  272. package/skills/minimax-docx/assets/xsd/common-types.xsd +159 -0
  273. package/skills/minimax-docx/assets/xsd/wml-subset.xsd +589 -0
  274. package/skills/minimax-docx/references/cjk_typography.md +357 -0
  275. package/skills/minimax-docx/references/cjk_university_template_guide.md +184 -0
  276. package/skills/minimax-docx/references/comments_guide.md +191 -0
  277. package/skills/minimax-docx/references/design_good_bad_examples.md +829 -0
  278. package/skills/minimax-docx/references/design_principles.md +819 -0
  279. package/skills/minimax-docx/references/openxml_element_order.md +308 -0
  280. package/skills/minimax-docx/references/openxml_encyclopedia_part1.md +4061 -0
  281. package/skills/minimax-docx/references/openxml_encyclopedia_part2.md +2820 -0
  282. package/skills/minimax-docx/references/openxml_encyclopedia_part3.md +3381 -0
  283. package/skills/minimax-docx/references/openxml_namespaces.md +82 -0
  284. package/skills/minimax-docx/references/openxml_units.md +72 -0
  285. package/skills/minimax-docx/references/scenario_a_create.md +284 -0
  286. package/skills/minimax-docx/references/scenario_b_edit_content.md +295 -0
  287. package/skills/minimax-docx/references/scenario_c_apply_template.md +456 -0
  288. package/skills/minimax-docx/references/track_changes_guide.md +200 -0
  289. package/skills/minimax-docx/references/troubleshooting.md +506 -0
  290. package/skills/minimax-docx/references/typography_guide.md +294 -0
  291. package/skills/minimax-docx/references/xsd_validation_guide.md +158 -0
  292. package/skills/minimax-docx/scripts/doc_to_docx.sh +40 -0
  293. package/skills/minimax-docx/scripts/docx_preview.sh +37 -0
  294. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/MiniMaxAIDocx.Cli.csproj +19 -0
  295. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/Program.cs +18 -0
  296. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/AnalyzeCommand.cs +147 -0
  297. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ApplyTemplateCommand.cs +322 -0
  298. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/CreateCommand.cs +324 -0
  299. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/DiffCommand.cs +155 -0
  300. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/EditContentCommand.cs +487 -0
  301. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/FixOrderCommand.cs +108 -0
  302. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/MergeRunsCommand.cs +122 -0
  303. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ValidateCommand.cs +107 -0
  304. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/MiniMaxAIDocx.Core.csproj +15 -0
  305. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/CommentSynchronizer.cs +169 -0
  306. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/ElementOrder.cs +80 -0
  307. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/NamespaceConstants.cs +42 -0
  308. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/RunMerger.cs +81 -0
  309. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/StyleAnalyzer.cs +81 -0
  310. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/TrackChangesHelper.cs +99 -0
  311. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/UnitConverter.cs +23 -0
  312. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples.cs +1832 -0
  313. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch1.cs +910 -0
  314. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch2.cs +999 -0
  315. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch3.cs +1048 -0
  316. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch4.cs +1038 -0
  317. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/CharacterFormattingSamples.cs +1020 -0
  318. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/DocumentCreationSamples.cs +1121 -0
  319. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FieldAndTocSamples.cs +624 -0
  320. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FootnoteAndCommentSamples.cs +675 -0
  321. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/HeaderFooterSamples.cs +838 -0
  322. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ImageSamples.cs +917 -0
  323. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ListAndNumberingSamples.cs +826 -0
  324. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ParagraphFormattingSamples.cs +1199 -0
  325. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/StyleSystemSamples.cs +1487 -0
  326. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TableSamples.cs +1163 -0
  327. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TrackChangesSamples.cs +595 -0
  328. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/CjkHelper.cs +39 -0
  329. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/FontDefaults.cs +24 -0
  330. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/PageSizes.cs +20 -0
  331. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/BusinessRuleValidator.cs +224 -0
  332. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/GateCheckValidator.cs +148 -0
  333. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/ValidationResult.cs +23 -0
  334. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/XsdValidator.cs +69 -0
  335. package/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.slnx +4 -0
  336. package/skills/minimax-docx/scripts/env_check.sh +196 -0
  337. package/skills/minimax-docx/scripts/setup.ps1 +274 -0
  338. package/skills/minimax-docx/scripts/setup.sh +504 -0
  339. package/skills/minimax-pdf/README.md +222 -0
  340. package/skills/minimax-pdf/SKILL.md +218 -0
  341. package/skills/minimax-pdf/design/design.md +381 -0
  342. package/skills/minimax-pdf/scripts/cover.py +1579 -0
  343. package/skills/minimax-pdf/scripts/fill_inspect.py +200 -0
  344. package/skills/minimax-pdf/scripts/fill_write.py +242 -0
  345. package/skills/minimax-pdf/scripts/make.sh +491 -0
  346. package/skills/minimax-pdf/scripts/merge.py +112 -0
  347. package/skills/minimax-pdf/scripts/palette.py +521 -0
  348. package/skills/minimax-pdf/scripts/reformat_parse.py +374 -0
  349. package/skills/minimax-pdf/scripts/render_body.py +1052 -0
  350. package/skills/minimax-pdf/scripts/render_cover.js +111 -0
  351. package/skills/minimax-xlsx/SKILL.md +156 -0
  352. package/skills/minimax-xlsx/references/create.md +691 -0
  353. package/skills/minimax-xlsx/references/edit.md +684 -0
  354. package/skills/minimax-xlsx/references/fix.md +37 -0
  355. package/skills/minimax-xlsx/references/format.md +768 -0
  356. package/skills/minimax-xlsx/references/ooxml-cheatsheet.md +231 -0
  357. package/skills/minimax-xlsx/references/read-analyze.md +97 -0
  358. package/skills/minimax-xlsx/references/validate.md +772 -0
  359. package/skills/minimax-xlsx/scripts/formula_check.py +422 -0
  360. package/skills/minimax-xlsx/scripts/libreoffice_recalc.py +248 -0
  361. package/skills/minimax-xlsx/scripts/shared_strings_builder.py +163 -0
  362. package/skills/minimax-xlsx/scripts/style_audit.py +575 -0
  363. package/skills/minimax-xlsx/scripts/xlsx_add_column.py +395 -0
  364. package/skills/minimax-xlsx/scripts/xlsx_insert_row.py +274 -0
  365. package/skills/minimax-xlsx/scripts/xlsx_pack.py +87 -0
  366. package/skills/minimax-xlsx/scripts/xlsx_reader.py +362 -0
  367. package/skills/minimax-xlsx/scripts/xlsx_shift_rows.py +396 -0
  368. package/skills/minimax-xlsx/scripts/xlsx_unpack.py +130 -0
  369. package/skills/minimax-xlsx/templates/minimal_xlsx/[Content_Types].xml +9 -0
  370. package/skills/minimax-xlsx/templates/minimal_xlsx/_rels/.rels +6 -0
  371. package/skills/minimax-xlsx/templates/minimal_xlsx/xl/_rels/workbook.xml.rels +19 -0
  372. package/skills/minimax-xlsx/templates/minimal_xlsx/xl/sharedStrings.xml +33 -0
  373. package/skills/minimax-xlsx/templates/minimal_xlsx/xl/styles.xml +160 -0
  374. package/skills/minimax-xlsx/templates/minimal_xlsx/xl/workbook.xml +30 -0
  375. package/skills/minimax-xlsx/templates/minimal_xlsx/xl/worksheets/sheet1.xml +70 -0
  376. package/skills/newsletter-generation/SKILL.md +71 -0
  377. package/skills/oss-release-readiness/SKILL.md +47 -0
  378. package/skills/parallel-subagent-dispatch/SKILL.md +58 -0
  379. package/skills/performance-optimization/SKILL.md +364 -0
  380. package/skills/planning-and-task-breakdown/SKILL.md +290 -0
  381. package/skills/pptx-generator/SKILL.md +275 -0
  382. package/skills/pptx-generator/references/design-system.md +392 -0
  383. package/skills/pptx-generator/references/editing.md +162 -0
  384. package/skills/pptx-generator/references/pitfalls.md +112 -0
  385. package/skills/pptx-generator/references/pptxgenjs.md +420 -0
  386. package/skills/pptx-generator/references/slide-types.md +413 -0
  387. package/skills/pr-test-analysis/SKILL.md +24 -0
  388. package/skills/react-native-dev/SKILL.md +180 -0
  389. package/skills/react-native-dev/references/animations.md +254 -0
  390. package/skills/react-native-dev/references/components.md +124 -0
  391. package/skills/react-native-dev/references/engineering.md +527 -0
  392. package/skills/react-native-dev/references/forms.md +300 -0
  393. package/skills/react-native-dev/references/native-capabilities.md +163 -0
  394. package/skills/react-native-dev/references/navigation.md +271 -0
  395. package/skills/react-native-dev/references/networking.md +346 -0
  396. package/skills/react-native-dev/references/performance.md +215 -0
  397. package/skills/react-native-dev/references/state-management.md +230 -0
  398. package/skills/react-native-dev/references/styling.md +117 -0
  399. package/skills/react-native-dev/references/testing.md +341 -0
  400. package/skills/requirements-grilling/SKILL.md +447 -0
  401. package/skills/requirements-grilling/references/ADR-FORMAT.md +46 -0
  402. package/skills/requirements-grilling/references/CONTEXT-FORMAT.md +41 -0
  403. package/skills/requirements-grilling/references/INTERVIEW-PACKET-FORMAT.md +62 -0
  404. package/skills/requirements-grilling/references/MIT-LICENSE-MATT-POCOCK.md +25 -0
  405. package/skills/requirements-grilling/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/LICENSE +21 -0
  406. package/skills/requirements-grilling/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/NOTICE.md +9 -0
  407. package/skills/requirements-grilling/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/interview-me/SKILL.upstream.md +225 -0
  408. package/skills/requirements-grilling/references/upstream/mattpocock-skills/9603c1cc8118d08bc1b3bf34cf714f62178dea3b/LICENSE +21 -0
  409. package/skills/requirements-grilling/references/upstream/mattpocock-skills/9603c1cc8118d08bc1b3bf34cf714f62178dea3b/NOTICE.md +12 -0
  410. package/skills/requirements-grilling/references/upstream/mattpocock-skills/9603c1cc8118d08bc1b3bf34cf714f62178dea3b/batch-grill-me/SKILL.upstream.md +15 -0
  411. package/skills/requirements-grilling/references/upstream/mattpocock-skills/9603c1cc8118d08bc1b3bf34cf714f62178dea3b/grill-me/SKILL.upstream.md +7 -0
  412. package/skills/requirements-grilling/references/upstream/mattpocock-skills/9603c1cc8118d08bc1b3bf34cf714f62178dea3b/grilling/SKILL.upstream.md +12 -0
  413. package/skills/review-pipeline/SKILL.md +38 -0
  414. package/skills/rose-memory/SKILL.md +210 -0
  415. package/skills/rose-memory/references/README.md +48 -0
  416. package/skills/rose-memory/references/memory_cli.py +2384 -0
  417. package/skills/rose-memory/references/schema.sql +315 -0
  418. package/skills/security-and-hardening/SKILL.md +369 -0
  419. package/skills/session-handoff/SKILL.md +88 -0
  420. package/skills/session-handoff/references/upstream/mattpocock-skills/391a2701dd948f94f56a39f7533f8eea9a859c87/LICENSE +21 -0
  421. package/skills/session-handoff/references/upstream/mattpocock-skills/391a2701dd948f94f56a39f7533f8eea9a859c87/NOTICE.md +9 -0
  422. package/skills/session-handoff/references/upstream/mattpocock-skills/391a2701dd948f94f56a39f7533f8eea9a859c87/productivity/handoff/SKILL.upstream.md +16 -0
  423. package/skills/session-handoff/scripts/session_handoff.py +764 -0
  424. package/skills/shader-dev/SKILL.md +316 -0
  425. package/skills/shader-dev/reference/ambient-occlusion.md +382 -0
  426. package/skills/shader-dev/reference/analytic-ray-tracing.md +651 -0
  427. package/skills/shader-dev/reference/anti-aliasing.md +71 -0
  428. package/skills/shader-dev/reference/atmospheric-scattering.md +571 -0
  429. package/skills/shader-dev/reference/camera-effects.md +80 -0
  430. package/skills/shader-dev/reference/cellular-automata.md +635 -0
  431. package/skills/shader-dev/reference/color-palette.md +481 -0
  432. package/skills/shader-dev/reference/csg-boolean-operations.md +466 -0
  433. package/skills/shader-dev/reference/domain-repetition.md +436 -0
  434. package/skills/shader-dev/reference/domain-warping.md +419 -0
  435. package/skills/shader-dev/reference/fluid-simulation.md +425 -0
  436. package/skills/shader-dev/reference/fractal-rendering.md +525 -0
  437. package/skills/shader-dev/reference/lighting-model.md +639 -0
  438. package/skills/shader-dev/reference/matrix-transform.md +535 -0
  439. package/skills/shader-dev/reference/multipass-buffer.md +571 -0
  440. package/skills/shader-dev/reference/normal-estimation.md +418 -0
  441. package/skills/shader-dev/reference/particle-system.md +589 -0
  442. package/skills/shader-dev/reference/path-tracing-gi.md +602 -0
  443. package/skills/shader-dev/reference/polar-uv-manipulation.md +521 -0
  444. package/skills/shader-dev/reference/post-processing.md +375 -0
  445. package/skills/shader-dev/reference/procedural-2d-pattern.md +439 -0
  446. package/skills/shader-dev/reference/procedural-noise.md +551 -0
  447. package/skills/shader-dev/reference/ray-marching.md +396 -0
  448. package/skills/shader-dev/reference/sdf-2d.md +724 -0
  449. package/skills/shader-dev/reference/sdf-3d.md +805 -0
  450. package/skills/shader-dev/reference/sdf-tricks.md +63 -0
  451. package/skills/shader-dev/reference/shadow-techniques.md +476 -0
  452. package/skills/shader-dev/reference/simulation-physics.md +644 -0
  453. package/skills/shader-dev/reference/sound-synthesis.md +578 -0
  454. package/skills/shader-dev/reference/terrain-rendering.md +839 -0
  455. package/skills/shader-dev/reference/texture-mapping-advanced.md +87 -0
  456. package/skills/shader-dev/reference/texture-sampling.md +553 -0
  457. package/skills/shader-dev/reference/volumetric-rendering.md +608 -0
  458. package/skills/shader-dev/reference/voronoi-cellular-noise.md +486 -0
  459. package/skills/shader-dev/reference/voxel-rendering.md +701 -0
  460. package/skills/shader-dev/reference/water-ocean.md +445 -0
  461. package/skills/shader-dev/reference/webgl-pitfalls.md +41 -0
  462. package/skills/shader-dev/techniques/ambient-occlusion.md +364 -0
  463. package/skills/shader-dev/techniques/analytic-ray-tracing.md +542 -0
  464. package/skills/shader-dev/techniques/anti-aliasing.md +124 -0
  465. package/skills/shader-dev/techniques/atmospheric-scattering.md +522 -0
  466. package/skills/shader-dev/techniques/camera-effects.md +115 -0
  467. package/skills/shader-dev/techniques/cellular-automata.md +531 -0
  468. package/skills/shader-dev/techniques/color-palette.md +380 -0
  469. package/skills/shader-dev/techniques/csg-boolean-operations.md +491 -0
  470. package/skills/shader-dev/techniques/domain-repetition.md +333 -0
  471. package/skills/shader-dev/techniques/domain-warping.md +414 -0
  472. package/skills/shader-dev/techniques/fluid-simulation.md +1175 -0
  473. package/skills/shader-dev/techniques/fractal-rendering.md +436 -0
  474. package/skills/shader-dev/techniques/lighting-model.md +527 -0
  475. package/skills/shader-dev/techniques/matrix-transform.md +455 -0
  476. package/skills/shader-dev/techniques/multipass-buffer.md +922 -0
  477. package/skills/shader-dev/techniques/normal-estimation.md +318 -0
  478. package/skills/shader-dev/techniques/particle-system.md +1203 -0
  479. package/skills/shader-dev/techniques/path-tracing-gi.md +623 -0
  480. package/skills/shader-dev/techniques/polar-uv-manipulation.md +373 -0
  481. package/skills/shader-dev/techniques/post-processing.md +788 -0
  482. package/skills/shader-dev/techniques/procedural-2d-pattern.md +346 -0
  483. package/skills/shader-dev/techniques/procedural-noise.md +554 -0
  484. package/skills/shader-dev/techniques/ray-marching.md +467 -0
  485. package/skills/shader-dev/techniques/sdf-2d.md +631 -0
  486. package/skills/shader-dev/techniques/sdf-3d.md +589 -0
  487. package/skills/shader-dev/techniques/sdf-tricks.md +100 -0
  488. package/skills/shader-dev/techniques/shadow-techniques.md +776 -0
  489. package/skills/shader-dev/techniques/simulation-physics.md +1542 -0
  490. package/skills/shader-dev/techniques/sound-synthesis.md +490 -0
  491. package/skills/shader-dev/techniques/terrain-rendering.md +408 -0
  492. package/skills/shader-dev/techniques/texture-mapping-advanced.md +121 -0
  493. package/skills/shader-dev/techniques/texture-sampling.md +382 -0
  494. package/skills/shader-dev/techniques/volumetric-rendering.md +375 -0
  495. package/skills/shader-dev/techniques/voronoi-cellular-noise.md +458 -0
  496. package/skills/shader-dev/techniques/voxel-rendering.md +985 -0
  497. package/skills/shader-dev/techniques/water-ocean.md +490 -0
  498. package/skills/shader-dev/techniques/webgl-pitfalls.md +170 -0
  499. package/skills/shipping-and-launch/SKILL.md +334 -0
  500. package/skills/silent-failure-hunting/SKILL.md +24 -0
  501. package/skills/source-driven-development/SKILL.md +223 -0
  502. package/skills/spec-driven-development/SKILL.md +235 -0
  503. package/skills/spec-driven-development/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/LICENSE +21 -0
  504. package/skills/spec-driven-development/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/NOTICE.md +9 -0
  505. package/skills/spec-driven-development/references/upstream/addyosmani-agent-skills/6bcfeb9dae52b11eaad23511acc165109746dbc3/spec-driven-development/SKILL.upstream.md +206 -0
  506. package/skills/strategy-stress-test/SKILL.md +185 -0
  507. package/skills/systematic-literature-review/SKILL.md +77 -0
  508. package/skills/test-document-generator/SKILL.md +152 -0
  509. package/skills/test-document-generator/references/test-document-template.md +45 -0
  510. package/skills/test-driven-development/SKILL.md +399 -0
  511. package/skills/write-skills/GLOSSARY.md +113 -0
  512. package/skills/write-skills/SKILL.md +133 -0
  513. package/skills/write-skills/references/upstream/mattpocock-skills/391a2701dd948f94f56a39f7533f8eea9a859c87/LICENSE +21 -0
  514. package/skills/write-skills/references/upstream/mattpocock-skills/391a2701dd948f94f56a39f7533f8eea9a859c87/NOTICE.md +9 -0
  515. package/skills/write-skills/references/upstream/mattpocock-skills/391a2701dd948f94f56a39f7533f8eea9a859c87/productivity/writing-great-skills/GLOSSARY.md +201 -0
  516. package/skills/write-skills/references/upstream/mattpocock-skills/391a2701dd948f94f56a39f7533f8eea9a859c87/productivity/writing-great-skills/SKILL.upstream.md +83 -0
  517. package/src/runtime/child-guard.ts +70 -0
  518. package/src/runtime/conflicts.ts +25 -0
  519. package/src/runtime/contracts.ts +9 -0
  520. package/src/runtime/doctor.ts +134 -0
  521. package/src/runtime/global-resources.ts +152 -0
  522. package/src/runtime/index.ts +23 -0
  523. package/src/runtime/lifecycle.ts +19 -0
  524. package/src/runtime/native-integrations.ts +44 -0
  525. package/src/runtime/path-boundaries.ts +69 -0
  526. package/src/runtime/registry.ts +213 -0
  527. package/src/runtime/roles.ts +64 -0
  528. package/src/runtime/rose-context.ts +24 -0
  529. package/src/runtime/subagents.ts +426 -0
  530. package/templates/APPEND_SYSTEM.md +12 -0
  531. package/upstream/aili-workflows.lock.json +3226 -0
@@ -0,0 +1,1203 @@
1
+ # Particle System
2
+
3
+ **IMPORTANT: GLSL ES 3.0 return values**: All code paths in non-void functions must return a value. Every branch of an if statement must have a return.
4
+
5
+ **IMPORTANT: Particle system time cycling**: Must use `mod(time - offset, period)` for cycle computation. **Never use `floor(time / period) * period`**! The latter causes all particles to have negative time initially, resulting in startup delay or blank rendering.
6
+
7
+ **IMPORTANT: Brightness budget (most common failure cause!)**: Each particle's `numerator / (dist² + epsilon)` peak = `numerator / epsilon`. **Total peak = N_particles x (numerator / epsilon) must be < 5.0** (single pass). Exceeding this budget causes washout even with Reinhard. See specific reference values in the comments of each template below. Multi-pass ping-pong systems have a stricter budget, see below.
8
+
9
+ **IMPORTANT: Particle color vs background contrast**: When particle color is close to the background (sand dust/snow/fog), visibility must be enhanced through at least one method: (1) brightness significantly higher than background (2) different hue (3) visible motion trail.
10
+
11
+ **IMPORTANT: Elongated glow (meteor/trail lines)**: Do not use `1/(distPerp² + tiny_epsilon)` for line glow — too-small epsilon makes the line center extremely bright. Correct approach: use `smoothstep` or `exp(-dist)` for lines, see meteor template below.
12
+
13
+ ### Correct Pattern
14
+ ```glsl
15
+ // Vertex shader
16
+ #version 300 es
17
+ in vec4 aPosition;
18
+ void main() {
19
+ gl_Position = aPosition;
20
+ }
21
+
22
+ // Fragment shader
23
+ #version 300 es
24
+ precision highp float;
25
+ uniform vec2 iResolution;
26
+ uniform float iTime;
27
+ out vec4 fragColor;
28
+
29
+ float hash11(float p) {
30
+ return fract(sin(p * 127.1) * 43758.5453);
31
+ }
32
+
33
+ void main() {
34
+ vec2 uv = gl_FragCoord.xy / iResolution.xy;
35
+ // ... particle system logic
36
+ fragColor = vec4(col, 1.0);
37
+ }
38
+ ```
39
+
40
+ ### Complete Single-File Template (Fireworks Particle System)
41
+
42
+ ```html
43
+ <!DOCTYPE html>
44
+ <html>
45
+ <head>
46
+ <meta charset="utf-8">
47
+ <title>Fireworks</title>
48
+ <style>
49
+ body { margin: 0; overflow: hidden; background: #000; }
50
+ canvas { display: block; width: 100vw; height: 100vh; }
51
+ </style>
52
+ </head>
53
+ <body>
54
+ <canvas id="c"></canvas>
55
+ <script>
56
+ const canvas = document.getElementById('c');
57
+ const gl = canvas.getContext('webgl2');
58
+
59
+ const vs = `#version 300 es
60
+ in vec4 aPosition;
61
+ void main() { gl_Position = aPosition; }`;
62
+
63
+ const fs = `#version 300 es
64
+ precision highp float;
65
+ uniform vec2 iResolution;
66
+ uniform float iTime;
67
+ out vec4 fragColor;
68
+
69
+ #define NUM_FIREWORKS 4
70
+ #define PARTICLES_PER_FIREWORK 40
71
+ #define PI 3.14159265
72
+
73
+ float hash11(float p) {
74
+ return fract(sin(p * 127.1) * 43758.5453);
75
+ }
76
+
77
+ vec3 hsv2rgb(vec3 c) {
78
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
79
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
80
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
81
+ }
82
+
83
+ void main() {
84
+ vec2 uv = (gl_FragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;
85
+ vec3 col = vec3(0.01, 0.01, 0.03);
86
+ float t = iTime;
87
+
88
+ for (int fw = 0; fw < NUM_FIREWORKS; fw++) {
89
+ float fwId = float(fw);
90
+ float launchTime = 1.5 + fwId * 1.8 + hash11(fwId * 7.3) * 1.5;
91
+ float cycleTime = 4.5;
92
+ float fireworkTime = mod(t - launchTime, cycleTime);
93
+
94
+ float launchDuration = 0.6;
95
+ float launchPhase = clamp(fireworkTime / launchDuration, 0.0, 1.0);
96
+
97
+ float launchX = (hash11(fwId * 13.7) - 0.5) * 1.2;
98
+ float launchY = -0.8;
99
+ float peakY = 0.2 + hash11(fwId * 17.3) * 0.4;
100
+
101
+ float baseHue = hash11(fwId * 23.0);
102
+
103
+ if (fireworkTime < launchDuration) {
104
+ vec2 rocketPos = vec2(launchX, mix(launchY, peakY, launchPhase));
105
+ vec2 rel = uv - rocketPos;
106
+ float dist = length(rel);
107
+ // Rocket head: peak = 0.008/0.002 = 4.0, only 1 point, OK
108
+ float rocket = 0.008 / (dist * dist + 0.002);
109
+ float tail = 0.004 / (length(vec2(rel.x * 4.0, max(rel.y, 0.0))) + 0.01);
110
+ col += vec3(1.0, 0.8, 0.5) * rocket;
111
+ col += vec3(1.0, 0.5, 0.2) * tail * (1.0 - launchPhase);
112
+ } else {
113
+ float burstTime = fireworkTime - launchDuration;
114
+ float burstDuration = cycleTime - launchDuration;
115
+ float burstPhase = burstTime / burstDuration;
116
+
117
+ for (int p = 0; p < PARTICLES_PER_FIREWORK; p++) {
118
+ float pId = float(p);
119
+ float angle = hash11(fwId * 100.0 + pId * 7.3) * PI * 2.0;
120
+ float speed = 0.3 + hash11(fwId * 100.0 + pId * 13.7) * 0.7;
121
+
122
+ vec2 particleDir = vec2(cos(angle), sin(angle));
123
+
124
+ float damping = exp(-burstPhase * 2.5);
125
+ float travelDist = speed * (1.0 - damping) / 2.5;
126
+ vec2 particlePos = vec2(launchX, peakY) + particleDir * travelDist;
127
+
128
+ particlePos.y -= 0.5 * 1.2 * burstTime * burstTime;
129
+
130
+ vec2 rel = uv - particlePos;
131
+ float dist = length(rel);
132
+
133
+ float fade = smoothstep(1.0, 0.0, burstPhase);
134
+ fade *= fade;
135
+
136
+ // IMPORTANT: Brightness budget: peak = 0.015/0.03 = 0.5, x 40 particles x fade ≈ total peak < 5.0
137
+ float intensity = fade * 0.015 / (dist * dist + 0.03);
138
+
139
+ float hueOffset = (hash11(pId * 3.7 + fwId * 11.0) - 0.5) * 0.15;
140
+ vec3 particleColor = hsv2rgb(vec3(baseHue + hueOffset, 0.8, 1.0));
141
+
142
+ col += particleColor * intensity;
143
+ }
144
+ }
145
+ }
146
+
147
+ col = col / (1.0 + col);
148
+ col = pow(col, vec3(0.9));
149
+ fragColor = vec4(col, 1.0);
150
+ }`;
151
+
152
+ function createShader(type, source) {
153
+ const s = gl.createShader(type);
154
+ gl.shaderSource(s, source);
155
+ gl.compileShader(s);
156
+ if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
157
+ console.error(gl.getShaderInfoLog(s));
158
+ }
159
+ return s;
160
+ }
161
+
162
+ const program = gl.createProgram();
163
+ gl.attachShader(program, createShader(gl.VERTEX_SHADER, vs));
164
+ gl.attachShader(program, createShader(gl.FRAGMENT_SHADER, fs));
165
+ gl.linkProgram(program);
166
+ gl.useProgram(program);
167
+
168
+ const buf = gl.createBuffer();
169
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
170
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1,1,-1,-1,1,1,1]), gl.STATIC_DRAW);
171
+ const aPos = gl.getAttribLocation(program, 'aPosition');
172
+ gl.enableVertexAttribArray(aPos);
173
+ gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
174
+
175
+ // Cache uniform locations (do NOT look up every frame - causes performance issues)
176
+ const iResolutionLoc = gl.getUniformLocation(program, 'iResolution');
177
+ const iTimeLoc = gl.getUniformLocation(program, 'iTime');
178
+
179
+ // Resize handler: only resize when window size actually changes
180
+ let lastWidth = 0, lastHeight = 0;
181
+ function resize() {
182
+ const w = window.innerWidth, h = window.innerHeight;
183
+ if (w !== lastWidth || h !== lastHeight) {
184
+ lastWidth = w; lastHeight = h;
185
+ canvas.width = w; canvas.height = h;
186
+ gl.viewport(0, 0, w, h);
187
+ }
188
+ }
189
+
190
+ function render(t) {
191
+ resize();
192
+ gl.uniform2f(iResolutionLoc, canvas.width, canvas.height);
193
+ gl.uniform1f(iTimeLoc, t * 0.001);
194
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
195
+ requestAnimationFrame(render);
196
+ }
197
+ requestAnimationFrame(render);
198
+ </script>
199
+ </body>
200
+ </html>
201
+ ```
202
+
203
+ ### Stateful Particle System HTML Template (Multi-Pass Ping-Pong)
204
+
205
+ Stateful particles (Boids, cloth, fluid particles, etc.) need Buffers for inter-frame state storage. The following JS skeleton demonstrates the correct WebGL2 multi-pass ping-pong structure; shader code is in Steps 4-5 below:
206
+
207
+ ```html
208
+ <!DOCTYPE html>
209
+ <html>
210
+ <head>
211
+ <meta charset="utf-8">
212
+ <title>Stateful Particles</title>
213
+ <style>
214
+ body { margin: 0; overflow: hidden; background: #000; }
215
+ canvas { display: block; width: 100vw; height: 100vh; }
216
+ </style>
217
+ </head>
218
+ <body>
219
+ <canvas id="c"></canvas>
220
+ <script>
221
+ let frameCount = 0;
222
+ let mouse = [0, 0, 0, 0];
223
+
224
+ const canvas = document.getElementById('c');
225
+ const gl = canvas.getContext('webgl2');
226
+ const ext = gl.getExtension('EXT_color_buffer_float');
227
+
228
+ function createShader(type, src) {
229
+ const s = gl.createShader(type);
230
+ gl.shaderSource(s, src);
231
+ gl.compileShader(s);
232
+ if (!gl.getShaderParameter(s, gl.COMPILE_STATUS))
233
+ console.error(gl.getShaderInfoLog(s));
234
+ return s;
235
+ }
236
+ function createProgram(vsSrc, fsSrc) {
237
+ const p = gl.createProgram();
238
+ gl.attachShader(p, createShader(gl.VERTEX_SHADER, vsSrc));
239
+ gl.attachShader(p, createShader(gl.FRAGMENT_SHADER, fsSrc));
240
+ gl.linkProgram(p);
241
+ return p;
242
+ }
243
+
244
+ const vsSource = `#version 300 es
245
+ in vec2 pos;
246
+ void main(){ gl_Position=vec4(pos,0,1); }`;
247
+
248
+ // fsBuffer: particle physics update (see Step 4)
249
+ // fsImage: particle rendering (see Step 5)
250
+ const progBuf = createProgram(vsSource, fsBuffer);
251
+ const progImg = createProgram(vsSource, fsImage);
252
+
253
+ function createFBO(w, h) {
254
+ const tex = gl.createTexture();
255
+ gl.bindTexture(gl.TEXTURE_2D, tex);
256
+ const fmt = ext ? gl.RGBA16F : gl.RGBA8;
257
+ const typ = ext ? gl.FLOAT : gl.UNSIGNED_BYTE;
258
+ gl.texImage2D(gl.TEXTURE_2D, 0, fmt, w, h, 0, gl.RGBA, typ, null);
259
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
260
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
261
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
262
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
263
+ const fbo = gl.createFramebuffer();
264
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
265
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
266
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
267
+ return { fbo, tex };
268
+ }
269
+
270
+ let W, H, bufA, bufB;
271
+
272
+ const vao = gl.createVertexArray();
273
+ gl.bindVertexArray(vao);
274
+ const vbo = gl.createBuffer();
275
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
276
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 1,-1, -1,1, 1,1]), gl.STATIC_DRAW);
277
+ gl.enableVertexAttribArray(0);
278
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
279
+
280
+ function resize() {
281
+ canvas.width = W = innerWidth;
282
+ canvas.height = H = innerHeight;
283
+ bufA = createFBO(W, H);
284
+ bufB = createFBO(W, H);
285
+ frameCount = 0;
286
+ }
287
+ addEventListener('resize', resize);
288
+ resize();
289
+
290
+ canvas.addEventListener('mousedown', e => { mouse[2] = e.clientX; mouse[3] = H - e.clientY; });
291
+ canvas.addEventListener('mouseup', () => { mouse[2] = 0; mouse[3] = 0; });
292
+ canvas.addEventListener('mousemove', e => { mouse[0] = e.clientX; mouse[1] = H - e.clientY; });
293
+
294
+ function render(t) {
295
+ t *= 0.001;
296
+ // Buffer pass: read bufA → write bufB
297
+ gl.useProgram(progBuf);
298
+ gl.bindFramebuffer(gl.FRAMEBUFFER, bufB.fbo);
299
+ gl.viewport(0, 0, W, H);
300
+ gl.activeTexture(gl.TEXTURE0);
301
+ gl.bindTexture(gl.TEXTURE_2D, bufA.tex);
302
+ gl.uniform1i(gl.getUniformLocation(progBuf, 'iChannel0'), 0);
303
+ gl.uniform2f(gl.getUniformLocation(progBuf, 'iResolution'), W, H);
304
+ gl.uniform1f(gl.getUniformLocation(progBuf, 'iTime'), t);
305
+ gl.uniform1i(gl.getUniformLocation(progBuf, 'iFrame'), frameCount);
306
+ gl.uniform4f(gl.getUniformLocation(progBuf, 'iMouse'), ...mouse);
307
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
308
+ [bufA, bufB] = [bufB, bufA];
309
+
310
+ // Image pass: read bufA → screen
311
+ gl.useProgram(progImg);
312
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
313
+ gl.viewport(0, 0, W, H);
314
+ gl.activeTexture(gl.TEXTURE0);
315
+ gl.bindTexture(gl.TEXTURE_2D, bufA.tex);
316
+ gl.uniform1i(gl.getUniformLocation(progImg, 'iChannel0'), 0);
317
+ gl.uniform2f(gl.getUniformLocation(progImg, 'iResolution'), W, H);
318
+ gl.uniform1f(gl.getUniformLocation(progImg, 'iTime'), t);
319
+ gl.uniform1i(gl.getUniformLocation(progImg, 'iFrame'), frameCount);
320
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
321
+
322
+ frameCount++;
323
+ requestAnimationFrame(render);
324
+ }
325
+ requestAnimationFrame(render);
326
+ </script>
327
+ </body>
328
+ </html>
329
+ ```
330
+
331
+ ### Star Field Function Template (For Meteors, Fireworks, and Other Night Sky Scenes)
332
+
333
+ **IMPORTANT: Star visibility**: Stars must be clearly visible in screenshots as individual light points. Use `exp(-dist*dist*k)` for sharp Gaussian dots rather than `1/(dist²+eps)` broad glow. Each star's peak brightness should be at least 0.3 to be visible against a dark background.
334
+
335
+ ```glsl
336
+ #define NUM_STARS 200
337
+
338
+ vec3 starField(vec2 uv) {
339
+ vec3 col = vec3(0.0);
340
+ for (int i = 0; i < NUM_STARS; i++) {
341
+ float fi = float(i);
342
+ vec2 starPos = vec2(hash11(fi * 13.7 + 1.3), hash11(fi * 7.3 + 91.1));
343
+ starPos = starPos * 2.0 - 1.0;
344
+ float brightness = 0.3 + 0.7 * pow(hash11(fi * 3.1 + 47.0), 2.0);
345
+ float twinkle = 0.7 + 0.3 * sin(iTime * (1.0 + hash11(fi * 5.7) * 3.0) + fi * 6.28);
346
+ brightness *= twinkle;
347
+ float dist = length(uv - starPos);
348
+ // Sharp Gaussian dot: peak = brightness (0.3~1.0), very small radius, no accumulation washout
349
+ float glow = brightness * exp(-dist * dist * 8000.0);
350
+ // Add soft halo to make stars more visible
351
+ glow += brightness * 0.0008 / (dist * dist + 0.003);
352
+ float temp = hash11(fi * 11.3 + 23.0);
353
+ vec3 starCol = mix(vec3(0.6, 0.7, 1.0), vec3(1.0, 0.9, 0.7), temp);
354
+ col += starCol * glow;
355
+ }
356
+ return col;
357
+ }
358
+ ```
359
+
360
+ ### Incorrect Pattern (Do Not Do This)
361
+ ```glsl
362
+ // WRONG: cannot write this in standalone HTML
363
+ void mainImage(out vec4 fragColor, in vec2 fragCoord) { ... }
364
+ void main() {
365
+ mainImage(fragColor, fragCoord); // compilation error!
366
+ }
367
+ ```
368
+
369
+ ## ShaderToy vs Standalone HTML Code Templates
370
+
371
+ The following code examples fall into two categories; be sure to use the correct template:
372
+
373
+ ### Standalone HTML Template (complete example provided above)
374
+
375
+ ### ShaderToy Template (for the ShaderToy website)
376
+
377
+ ## Use Cases
378
+ - **Stateless particle effects**: fireworks, starfields, campfire/flames (flying embers), orbiting light points, and other decorative effects that don't need inter-frame memory
379
+ - **Stateful physics particles**: flocking/boids, raindrops, cloth, fluids, and other simulations requiring persistent position and velocity
380
+ - **Motion blur and trails**: particle trajectories needing afterglow or halo effects
381
+ - **Large-scale particle management**: real-time rendering and interaction with hundreds to thousands of particles
382
+ - **Weather/atmospheric effects**: sandstorms, blizzards, volcanic ash, and other vortex-driven particle systems
383
+ - **Magic/geometric arrays**: magic dust, spiraling ascending light points, magic circle rings, iridescent shimmering particles
384
+
385
+ Core decision tree: Do particles need inter-frame memory?
386
+ - **No** → Single-pass stateless system (using loops + hash functions)
387
+ - **Yes** → Multi-pass stateful system (using Buffer for position/velocity storage)
388
+
389
+ ## Core Principles
390
+
391
+ Particle systems manage collections of many independent entities, each with position, velocity, lifetime, and other attributes.
392
+
393
+ **Stateless paradigm**: All attributes are recomputed each frame from particle ID and time, no Buffer needed.
394
+ ```
395
+ position_i = trajectory(id_i, time) + randomOffset(hash(id_i))
396
+ lifetime_i = fract((time - spawnTime_i) / lifeDuration_i)
397
+ ```
398
+
399
+ **Stateful paradigm**: Particle state is stored in Buffer texture pixels, each frame reading → computing → writing back.
400
+ ```
401
+ // Euler method
402
+ velocity += acceleration * dt
403
+ position += velocity * dt
404
+
405
+ // Verlet integration (no explicit velocity, more stable)
406
+ newPos = 2 * currentPos - previousPos + acceleration * dt²
407
+ ```
408
+
409
+ **Rendering**: Distance-based falloff `intensity = brightness / (dist² + epsilon)`, with multi-particle superposition creating metaball fusion effects.
410
+
411
+ ## Implementation Steps
412
+
413
+ ### Step 1: Hash Random Functions
414
+ ```glsl
415
+ // 1D -> 1D hash, returns [0, 1)
416
+ float hash11(float p) {
417
+ return fract(sin(p * 127.1) * 43758.5453);
418
+ }
419
+
420
+ // 1D -> 2D hash
421
+ vec2 hash12(float p) {
422
+ vec3 p3 = fract(vec3(p) * vec3(0.1031, 0.1030, 0.0973));
423
+ p3 += dot(p3, p3.yzx + 33.33);
424
+ return fract((p3.xx + p3.yz) * p3.zy);
425
+ }
426
+
427
+ // 3D -> 3D hash
428
+ vec3 hash33(vec3 p) {
429
+ p = fract(p * vec3(443.897, 397.297, 491.187));
430
+ p += dot(p.zxy, p.yxz + 19.19);
431
+ return fract(vec3(p.x * p.y, p.z * p.x, p.y * p.z)) - 0.5;
432
+ }
433
+ ```
434
+
435
+ ### Step 2: Particle Lifecycle Management
436
+ ```glsl
437
+ #define NUM_PARTICLES 100
438
+ #define LIFETIME_MIN 1.0
439
+ #define LIFETIME_MAX 3.0
440
+ #define START_TIME 2.0
441
+
442
+ // Returns: x = normalized age [0,1], y = life cycle number
443
+ vec2 particleAge(int id, float time) {
444
+ float spawnTime = START_TIME * hash11(float(id) * 2.0);
445
+ float lifetime = mix(LIFETIME_MIN, LIFETIME_MAX, hash11(float(id) * 3.0 - 35.0));
446
+ float age = mod(time - spawnTime, lifetime);
447
+ float run = floor((time - spawnTime) / lifetime);
448
+ return vec2(age / lifetime, run);
449
+ }
450
+ ```
451
+
452
+ ### Step 3: Stateless Particle Position Computation
453
+ ```glsl
454
+ #define GRAVITY vec2(0.0, -4.5)
455
+ #define DRIFT_MAX vec2(0.28, 0.28)
456
+
457
+ // Harmonic superposition for smooth main trajectory
458
+ float harmonics(vec3 freq, vec3 amp, vec3 phase, float t) {
459
+ float val = 0.0;
460
+ for (int h = 0; h < 3; h++)
461
+ val += amp[h] * cos(t * freq[h] * 6.2832 + phase[h] / 360.0 * 6.2832);
462
+ return (1.0 + val) / 2.0;
463
+ }
464
+
465
+ vec2 particlePosition(int id, float time) {
466
+ vec2 ageInfo = particleAge(id, time);
467
+ float age = ageInfo.x;
468
+ float run = ageInfo.y;
469
+
470
+ float slowTime = time * 0.1;
471
+ vec2 mainPos = vec2(
472
+ harmonics(vec3(0.4, 0.66, 0.78), vec3(0.8, 0.24, 0.18), vec3(0.0, 45.0, 55.0), slowTime),
473
+ harmonics(vec3(0.415, 0.61, 0.82), vec3(0.72, 0.28, 0.15), vec3(90.0, 120.0, 10.0), slowTime)
474
+ );
475
+
476
+ vec2 drift = DRIFT_MAX * (vec2(hash11(float(id) * 3.0 + run * 4.0),
477
+ hash11(float(id) * 7.0 - run * 2.5)) - 0.5) * age;
478
+ vec2 grav = GRAVITY * age * age * 0.5;
479
+
480
+ return mainPos + drift + grav;
481
+ }
482
+ ```
483
+
484
+ ### Step 4: Buffer-Stored Particle State (Stateful System)
485
+ ```glsl
486
+ // === Buffer A: Particle Physics Update ===
487
+ // IMPORTANT: Multi-pass system warning: each fragment shader is compiled independently, helper functions must be redefined in each shader!
488
+ #define NUM_PARTICLES 40
489
+ #define MAX_VEL 0.5
490
+ #define MAX_ACC 3.0
491
+ #define RESIST 0.2
492
+ #define DT 0.03
493
+
494
+ // Helper functions that must be defined in the Buffer A shader
495
+ float hash11(float p) {
496
+ return fract(sin(p * 127.1) * 43758.5453);
497
+ }
498
+
499
+ vec2 hash12(float p) {
500
+ vec3 p3 = fract(vec3(p) * vec3(0.1031, 0.1030, 0.0973));
501
+ p3 += dot(p3, p3.yzx + 33.33);
502
+ return fract((p3.xx + p3.yz) * p3.zy);
503
+ }
504
+
505
+ vec4 loadParticle(float i) {
506
+ return texelFetch(iChannel0, ivec2(i, 0), 0);
507
+ }
508
+
509
+ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
510
+ if (fragCoord.y > 0.5 || fragCoord.x > float(NUM_PARTICLES)) discard;
511
+
512
+ float id = floor(fragCoord.x);
513
+ vec2 res = iResolution.xy / iResolution.y;
514
+
515
+ if (iFrame < 5) {
516
+ vec2 rng = hash12(id);
517
+ fragColor = vec4(0.1 + 0.8 * rng * res, 0.0, 0.0);
518
+ return;
519
+ }
520
+
521
+ vec4 particle = loadParticle(id); // xy = pos, zw = vel
522
+ vec2 pos = particle.xy;
523
+ vec2 vel = particle.zw;
524
+
525
+ vec2 force = vec2(0.0);
526
+ force += 0.8 * (1.0 / abs(pos) - 1.0 / abs(res - pos)); // boundary repulsion
527
+ for (float i = 0.0; i < float(NUM_PARTICLES); i++) { // inter-particle interaction
528
+ if (i == id) continue;
529
+ vec4 other = loadParticle(i);
530
+ vec2 w = pos - other.xy;
531
+ float d = length(w);
532
+ if (d > 0.0)
533
+ force -= w * (6.3 + log(d * d * 0.02)) / exp(d * d * 2.4) / d;
534
+ }
535
+ force -= vel * RESIST / DT; // friction
536
+
537
+ vec2 acc = force;
538
+ float a = length(acc);
539
+ acc *= a > MAX_ACC ? MAX_ACC / a : 1.0;
540
+ vel += acc * DT;
541
+ float v = length(vel);
542
+ vel *= v > MAX_VEL ? MAX_VEL / v : 1.0;
543
+ pos += vel * DT;
544
+
545
+ fragColor = vec4(pos, vel);
546
+ }
547
+ ```
548
+
549
+ ### Step 5: Particle Rendering — Metaball Style
550
+ // IMPORTANT: Multi-pass system warning: Image shader must define all the following helper functions (compiled independently)!
551
+ ```glsl
552
+ #define BRIGHTNESS 0.002
553
+ #define COLOR_START vec3(0.0, 0.64, 0.2)
554
+ #define COLOR_END vec3(0.06, 0.35, 0.85)
555
+
556
+ // Helper functions that must be defined in the Image shader
557
+ float hash11(float p) {
558
+ return fract(sin(p * 127.1) * 43758.5453);
559
+ }
560
+
561
+ vec2 hash12(float p) {
562
+ vec3 p3 = fract(vec3(p) * vec3(0.1031, 0.1030, 0.0973));
563
+ p3 += dot(p3, p3.yzx + 33.33);
564
+ return fract((p3.xx + p3.yz) * p3.zy);
565
+ }
566
+
567
+ vec4 loadParticle(float i) {
568
+ return texelFetch(iChannel0, ivec2(i, 0), 0);
569
+ }
570
+
571
+ // HSV to RGB (correct implementation)
572
+ vec3 hsv2rgb(vec3 c) {
573
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
574
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
575
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
576
+ }
577
+
578
+ vec3 renderParticles(vec2 uv) {
579
+ vec3 col = vec3(0.0);
580
+ float totalWeight = 0.0;
581
+ for (int i = 0; i < NUM_PARTICLES; i++) {
582
+ vec4 particle = loadParticle(float(i));
583
+ vec2 p = uv - particle.xy;
584
+ float mb = BRIGHTNESS / dot(p, p);
585
+ totalWeight += mb;
586
+ float ratio = length(particle.zw) / MAX_VEL;
587
+ vec3 pcol = mix(COLOR_START, COLOR_END, ratio);
588
+ col = mix(col, pcol, mb / totalWeight);
589
+ }
590
+ totalWeight /= float(NUM_PARTICLES);
591
+ col = normalize(col) * clamp(totalWeight, 0.0, 0.4);
592
+ return col;
593
+ }
594
+ ```
595
+
596
+ ### Step 6: Frame Feedback Motion Blur
597
+ ```glsl
598
+ // IMPORTANT: Ping-pong brightness budget (most common washout cause!):
599
+ // Steady-state brightness = singleFrameContribution / (1 - TRAIL_DECAY)
600
+ // decay=0.88 → 8.3x amplification, decay=0.95 → 20x amplification
601
+ // Budget formula: N_particles x (numerator/epsilon) x 1/(1-decay) < 10.0
602
+ //
603
+ // Safe parameter lookup table (decay=0.88, 8.3x amplification):
604
+ // 20 particles → single particle peak < 0.06 (numerator=0.002, epsilon=0.03)
605
+ // 50 particles → single particle peak < 0.024 (numerator=0.001, epsilon=0.04)
606
+ // 100 particles → single particle peak < 0.012 (numerator=0.0005, epsilon=0.04)
607
+ //
608
+ // Safe parameter lookup table (decay=0.92, 12.5x amplification):
609
+ // 20 particles → single particle peak < 0.04 (numerator=0.001, epsilon=0.03)
610
+ // 50 particles → single particle peak < 0.016 (numerator=0.0005, epsilon=0.03)
611
+ // 100 particles → single particle peak < 0.008 (numerator=0.0003, epsilon=0.04)
612
+ #define TRAIL_DECAY 0.88
613
+
614
+ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
615
+ vec2 uv = fragCoord / iResolution.xy;
616
+ vec3 prev = texture(iChannel0, uv).rgb * TRAIL_DECAY;
617
+ vec3 current = renderParticles(fragCoord / iResolution.y);
618
+ fragColor = vec4(prev + current, 1.0);
619
+ }
620
+ ```
621
+
622
+ ### Step 7: HSV Coloring & Star Glare Effect
623
+ ```glsl
624
+ // HSV to RGB (correct implementation)
625
+ vec3 hsv2rgb(vec3 c) {
626
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
627
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
628
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
629
+ }
630
+
631
+ // Star glare: thin rays in horizontal/vertical/diagonal directions
632
+ float starGlare(vec2 relPos, float intensity) {
633
+ vec2 stretch = vec2(9.0, 0.32);
634
+ float dh = length(relPos * stretch);
635
+ float dv = length(relPos * stretch.yx);
636
+ vec2 diagPos = 0.707 * vec2(dot(relPos, vec2(1, 1)), dot(relPos, vec2(1, -1)));
637
+ float dd1 = length(diagPos * vec2(13.0, 0.61));
638
+ float dd2 = length(diagPos * vec2(0.61, 13.0));
639
+ float glare = 0.25 / (dh * 3.0 + 0.01)
640
+ + 0.25 / (dv * 3.0 + 0.01)
641
+ + 0.19 / (dd1 * 3.0 + 0.01)
642
+ + 0.19 / (dd2 * 3.0 + 0.01);
643
+ return glare * intensity;
644
+ }
645
+ ```
646
+
647
+ ## Complete Code Template
648
+
649
+ Single-pass stateless particle system, runs directly in ShaderToy's Image tab:
650
+
651
+ ```glsl
652
+ // === Particle System — Stateless Single-Pass Template ===
653
+
654
+ #define NUM_PARTICLES 80
655
+ #define LIFETIME_MIN 1.0
656
+ #define LIFETIME_MAX 3.5
657
+ #define START_TIME 2.5
658
+ #define BRIGHTNESS 0.00004
659
+ #define GRAVITY vec2(0.0, -2.0)
660
+ #define DRIFT_SPEED 0.2
661
+ #define HUE_SHIFT 0.035
662
+ #define TRAIL_DECAY 0.92
663
+ #define STAR_ENABLED 1
664
+
665
+ #define PI 3.14159265
666
+ #define TAU 6.28318530
667
+
668
+ float hash11(float p) {
669
+ return fract(sin(p * 127.1) * 43758.5453);
670
+ }
671
+
672
+ vec3 hsv2rgb(vec3 c) {
673
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
674
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
675
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
676
+ }
677
+
678
+ float harmonics3(vec3 freq, vec3 amp, vec3 phase, float t) {
679
+ float val = 0.0;
680
+ for (int h = 0; h < 3; h++)
681
+ val += amp[h] * cos(t * freq[h] * TAU + phase[h] / 360.0 * TAU);
682
+ return (1.0 + val) * 0.5;
683
+ }
684
+
685
+ vec3 getLifecycle(int id, float time) {
686
+ float spawn = START_TIME * hash11(float(id) * 2.0);
687
+ float life = mix(LIFETIME_MIN, LIFETIME_MAX, hash11(float(id) * 3.0 - 35.0));
688
+ float age = mod(time - spawn, life);
689
+ float run = floor((time - spawn) / life);
690
+ return vec3(age / life, run, spawn);
691
+ }
692
+
693
+ vec2 getPosition(int id, float time) {
694
+ vec3 lc = getLifecycle(id, time);
695
+ float age = lc.x;
696
+ float run = lc.y;
697
+
698
+ float tfact = mix(6.0, 20.0, hash11(float(id) * 2.0 + 94.0 + run * 1.5));
699
+ float pt = (run * lc.x * mix(LIFETIME_MIN, LIFETIME_MAX, hash11(float(id)*3.0-35.0)) + lc.z) * (-1.0/tfact + 1.0) + time / tfact;
700
+
701
+ vec2 mainPos = vec2(
702
+ harmonics3(vec3(0.4, 0.66, 0.78), vec3(0.8, 0.24, 0.18), vec3(0.0, 45.0, 55.0), pt),
703
+ harmonics3(vec3(0.415, 0.61, 0.82), vec3(0.72, 0.28, 0.15), vec3(90.0, 120.0, 10.0), pt)
704
+ ) + vec2(0.35, 0.15);
705
+
706
+ vec2 drift = DRIFT_SPEED * (vec2(
707
+ hash11(float(id) * 3.0 - 23.0 + run * 4.0),
708
+ hash11(float(id) * 7.0 + 632.0 - run * 2.5)
709
+ ) - 0.5) * age;
710
+
711
+ vec2 grav = GRAVITY * age * age * 0.004;
712
+
713
+ return (mainPos + drift + grav) * vec2(0.6, 0.45);
714
+ }
715
+
716
+ float starGlare(vec2 rel) {
717
+ #if STAR_ENABLED == 0
718
+ return 0.0;
719
+ #endif
720
+ vec2 stretchHV = vec2(9.0, 0.32);
721
+ float dh = length(rel * stretchHV);
722
+ float dv = length(rel * stretchHV.yx);
723
+ vec2 dRel = 0.707 * vec2(dot(rel, vec2(1, 1)), dot(rel, vec2(1, -1)));
724
+ vec2 stretchDiag = vec2(13.0, 0.61);
725
+ float dd1 = length(dRel * stretchDiag);
726
+ float dd2 = length(dRel * stretchDiag.yx);
727
+ return 0.25 / (dh * 3.0 + 0.01) + 0.25 / (dv * 3.0 + 0.01)
728
+ + 0.19 / (dd1 * 3.0 + 0.01) + 0.19 / (dd2 * 3.0 + 0.01);
729
+ }
730
+
731
+ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
732
+ vec2 uv = fragCoord.xy / iResolution.xx;
733
+ float time = iTime * 0.75;
734
+
735
+ vec3 col = vec3(0.0);
736
+
737
+ for (int i = 1; i < NUM_PARTICLES; i++) {
738
+ vec3 lc = getLifecycle(i, time);
739
+ float age = lc.x;
740
+ float run = lc.y;
741
+
742
+ vec2 ppos = getPosition(i, time);
743
+ vec2 rel = uv - ppos;
744
+ float dist = length(rel);
745
+
746
+ float baseInt = mix(0.1, 3.2, hash11(run * 4.0 + float(i) - 55.0));
747
+ float glow = 1.0 / (dist * 3.0 + 0.015);
748
+
749
+ float star = starGlare(rel);
750
+ float intensity = baseInt * pow(glow + star, 2.3) / 40000.0;
751
+
752
+ intensity *= (1.0 - age);
753
+ intensity *= smoothstep(0.0, 0.15, age);
754
+ float sparkFreq = mix(2.5, 6.0, hash11(float(i) * 5.0 + 72.0 - run * 1.8));
755
+ intensity *= 0.5 * sin(sparkFreq * TAU * time) + 1.0;
756
+
757
+ float hue = mix(-0.13, 0.13, hash11(float(i) + 124.0 + run * 1.5)) + HUE_SHIFT * time;
758
+ float sat = mix(0.5, 0.9, hash11(float(i) * 6.0 + 44.0 + run * 3.3)) * 0.45 / max(intensity, 0.001);
759
+ col += hsv2rgb(vec3(hue, clamp(sat, 0.0, 1.0), intensity));
760
+ }
761
+
762
+ col = pow(max(col, 0.0), vec3(1.0 / 2.2));
763
+ fragColor = vec4(col, 1.0);
764
+ }
765
+ ```
766
+
767
+ ## Common Variants
768
+
769
+ ### Variant 1: Metaball Polar Coordinate Particles
770
+ ```glsl
771
+ float d = fract(time * 0.51 + 48934.4238 * sin(float(i) * 692.7398));
772
+ float angle = TAU * float(i) / float(NUM_PARTICLES);
773
+ vec2 particlePos = d * vec2(cos(angle), sin(angle)) * 4.0;
774
+
775
+ vec2 p = uv - particlePos;
776
+ float mb = 0.84 / dot(p, p);
777
+ col = mix(col, mix(startColor, endColor, d), mb / totalSum);
778
+ ```
779
+
780
+ ### Variant 2: Buffer Storage + Boids Flocking Behavior
781
+ ```glsl
782
+ vec2 sumForce = vec2(0.0);
783
+ for (float j = 0.0; j < NUM_PARTICLES; j++) {
784
+ if (j == id) continue;
785
+ vec4 other = texelFetch(iChannel0, ivec2(j, 0), 0);
786
+ vec2 w = pos - other.xy;
787
+ float d = length(w);
788
+ sumForce -= w * (6.3 + log(d * d * 0.02)) / exp(d * d * 2.4) / d;
789
+ }
790
+ sumForce -= vel * 0.2 / dt;
791
+ ```
792
+
793
+ ### Variant 3: Verlet Integration Cloth Simulation
794
+ ```glsl
795
+ vec2 newPos = 2.0 * particle.xy - particle.zw + vec2(0.0, -0.6) * dt * dt;
796
+ particle.zw = particle.xy;
797
+ particle.xy = newPos;
798
+
799
+ vec4 neighbor = texelFetch(iChannel0, neighborId, 0);
800
+ vec2 delta = neighbor.xy - particle.xy;
801
+ float dist = length(delta);
802
+ float restLength = 0.1;
803
+ particle.xy += 0.1 * (dist - restLength) * (delta / dist);
804
+ ```
805
+
806
+ ### Variant 4: 3D Particles + Ray Rendering
807
+ ```glsl
808
+ vec3 ro = vec3(0.0, 0.0, 2.5);
809
+ vec3 rd = normalize(vec3(uv, -0.5));
810
+ for (int i = 0; i < numParticles; i++) {
811
+ vec3 pos = texture(iChannel0, vec2(i, 100.0) * w).rgb;
812
+ float d = dot(cross(pos - ro, rd), cross(pos - ro, rd));
813
+ d *= 1000.0;
814
+ float glow = 0.14 / (pow(d, 1.1) + 0.03);
815
+ col += glow * particleColor;
816
+ }
817
+ ```
818
+
819
+ ### Variant 5: Raindrop Particles (3D Scene Integration)
820
+ ```glsl
821
+ float speedScale = 0.0015 * (0.1 + 1.9 * sin(PI * 0.5 * pow(age / lifetime, 2.0)));
822
+ particle.x += (windShieldOffset.x + windIntensity * dot(rayRight, windDir)) * fallSpeed * speedScale * dt;
823
+ particle.y += (windShieldOffset.y + windIntensity * dot(rayUp, windDir)) * fallSpeed * speedScale * dt;
824
+ particle.xy += 0.001 * (randVec2(particle.xy + iTime) - 0.5) * jitterSpeed * dt;
825
+ if (particle.z > particle.a) {
826
+ particle.xy = vec2(rand(seedX), rand(seedY)) * iResolution.xy;
827
+ particle.a = lifetimeMin + rand(pid) * (lifetimeMax - lifetimeMin);
828
+ particle.z = 0.0;
829
+ }
830
+ ```
831
+
832
+ ### Variant 6: Vortex/Storm Particle System (Sandstorm, Blizzard, Whirlwind, etc.)
833
+
834
+ Uses stateless single pass. Key: spiral trajectory + high-visibility particles + vortex eye dark zone + separated background fog layer.
835
+
836
+ ```glsl
837
+ // IMPORTANT: Particle color must be 2-3x brighter than background to be visible (sand-colored particles on sand-colored background easily disappear)
838
+ // IMPORTANT: Brightness budget: 150 particles x peak(0.005/0.003=1.67) x fade(avg~0.3) ≈ 75, overexposed!
839
+ // Must increase epsilon or decrease numerator. Safe values: numerator=0.002, epsilon=0.008 → peak=0.25, total=11 → OK after Reinhard
840
+ #define NUM_DUST 150
841
+ #define VORTEX_CENTER vec2(0.0)
842
+
843
+ void main() {
844
+ vec2 uv = (gl_FragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;
845
+ float t = iTime;
846
+
847
+ vec3 bg = mix(vec3(0.25, 0.18, 0.08), vec3(0.4, 0.28, 0.12), gl_FragCoord.y / iResolution.y);
848
+
849
+ vec3 col = vec3(0.0);
850
+ for (int i = 0; i < NUM_DUST; i++) {
851
+ float fi = float(i);
852
+ float life = mix(2.0, 5.0, hash11(fi * 3.7));
853
+ float age = mod(t - hash11(fi * 2.0) * life, life);
854
+ float norm = age / life;
855
+
856
+ float initAngle = hash11(fi * 7.3) * 6.2832;
857
+ float initR = 0.05 + hash11(fi * 11.0) * 0.5;
858
+ float angularSpeed = 2.0 / (0.3 + initR);
859
+ float angle = initAngle + norm * angularSpeed;
860
+ float radius = initR + norm * 0.15;
861
+
862
+ vec2 pos = VORTEX_CENTER + vec2(cos(angle), sin(angle)) * radius;
863
+
864
+ vec2 rel = uv - pos;
865
+ float dist = length(rel);
866
+
867
+ float fade = smoothstep(0.0, 0.1, norm) * smoothstep(1.0, 0.5, norm);
868
+ // Safe brightness: peak = 0.002/0.008 = 0.25, x 150 x avg_fade(0.3) ≈ 11 → Reinhard OK
869
+ float glow = 0.002 / (dist * dist + 0.008) * fade;
870
+
871
+ // Particles need to be noticeably brighter than background, use light sand + white blend
872
+ vec3 dustColor = mix(vec3(1.0, 0.9, 0.6), vec3(1.0, 0.95, 0.85), hash11(fi * 5.0));
873
+ col += dustColor * glow;
874
+ }
875
+
876
+ float eyeDist = length(uv - VORTEX_CENTER);
877
+ float eye = smoothstep(0.06, 0.15, eyeDist);
878
+
879
+ vec3 final = bg + col * eye;
880
+ final = final / (1.0 + final);
881
+ fragColor = vec4(final, 1.0);
882
+ }
883
+ ```
884
+
885
+ ### Variant 7: Meteor/Trail Line Rendering (Single-Pass Stateless)
886
+
887
+ Meteors, magic projectiles, etc. need elongated glow (stretched luminous lines). **Do not use `1/(distPerp² + tiny_epsilon)` for lines** — too-small epsilon makes line centers extremely bright and washed out. Use `exp(-dist)` or `smoothstep` for safe line glow.
888
+
889
+ **IMPORTANT: Common meteor failures**: (1) Star background too dark to see — must call `starField()` above and ensure stars use Gaussian dots `exp(-dist²*k)` for rendering (2) Meteor trail too faint — `core` multiplier should be at least 0.15, each step after dividing by `NUM_TRAIL_STEPS` still needs >= 0.005 contribution
890
+
891
+ ```glsl
892
+ #define NUM_METEORS 6
893
+ #define NUM_TRAIL_STEPS 20
894
+
895
+ void main() {
896
+ vec2 uv = (gl_FragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;
897
+ float t = iTime;
898
+
899
+ // Deep blue night sky background + must call starField to draw stars
900
+ vec3 col = vec3(0.005, 0.005, 0.02);
901
+ col += starField(uv);
902
+
903
+ for (int m = 0; m < NUM_METEORS; m++) {
904
+ float fm = float(m);
905
+ float cycleTime = mix(3.0, 7.0, hash11(fm * 17.3));
906
+ float meteorTime = mod(t - hash11(fm * 23.7) * cycleTime, cycleTime);
907
+ float travelDuration = mix(0.5, 1.2, hash11(fm * 31.1));
908
+
909
+ if (meteorTime > travelDuration + 0.3) continue;
910
+
911
+ float angle = mix(-0.4, -1.3, hash11(fm * 41.3));
912
+ vec2 dir = normalize(vec2(cos(angle), sin(angle)));
913
+ vec2 startPos = vec2(
914
+ mix(-0.3, 0.8, hash11(fm * 53.7)),
915
+ mix(0.2, 0.7, hash11(fm * 61.1))
916
+ );
917
+ float speed = mix(1.0, 2.0, hash11(fm * 71.3));
918
+ float headT = clamp(meteorTime / travelDuration, 0.0, 1.0);
919
+ vec2 headPos = startPos + dir * speed * headT;
920
+
921
+ float headFade = smoothstep(0.0, 0.1, meteorTime)
922
+ * smoothstep(travelDuration + 0.3, travelDuration, meteorTime);
923
+
924
+ float trailLen = mix(0.15, 0.35, hash11(fm * 83.7));
925
+
926
+ for (int s = 0; s < NUM_TRAIL_STEPS; s++) {
927
+ float sf = float(s) / float(NUM_TRAIL_STEPS);
928
+ vec2 samplePos = headPos - dir * trailLen * sf;
929
+ vec2 rel = uv - samplePos;
930
+
931
+ float distPerp = abs(dot(rel, vec2(-dir.y, dir.x)));
932
+
933
+ // Line width: narrow at head, wide at tail
934
+ float width = mix(0.003, 0.015, sf);
935
+ // core multiplier 0.15 ensures trail is visible even under SwiftShader
936
+ float core = exp(-distPerp / width) * 0.15;
937
+
938
+ float trailFade = (1.0 - sf) * (1.0 - sf);
939
+ float intensity = core * trailFade * headFade / float(NUM_TRAIL_STEPS);
940
+
941
+ float hue = mix(0.05, 0.12, sf);
942
+ vec3 meteorCol = hsv2rgb(vec3(hue, mix(0.1, 0.4, sf), 1.0));
943
+ col += meteorCol * intensity;
944
+ }
945
+
946
+ // Meteor head: bright point
947
+ float headDist = length(uv - headPos);
948
+ float headGlow = headFade * 0.005 / (headDist * headDist + 0.0008);
949
+ col += vec3(1.0, 0.95, 0.85) * headGlow;
950
+ }
951
+
952
+ col = col / (1.0 + col);
953
+ col = pow(col, vec3(0.95));
954
+ fragColor = vec4(col, 1.0);
955
+ }
956
+ ```
957
+
958
+ ### Variant 8: Fountain/Upward Jet Particle System (Single-Pass Stateless)
959
+
960
+ Water/sparks jetting upward from a point, parabolic descent. Key: **Particles must be sharp, individually visible points** (small epsilon), not just a diffuse glow blob. Must include: (1) main water column particles (upward jet + parabola) (2) splash particles (spread sideways after hitting water) (3) water surface/pool visuals.
961
+
962
+ **IMPORTANT: Most common fountain failure**: Only produces blurry glow without visible individual water droplet trajectories! Must use small epsilon (<=0.002) so each particle is clearly visible as an individual light point. Numerator must also be proportionally reduced to control total brightness.
963
+
964
+ ```glsl
965
+ #define NUM_WATER 60
966
+ #define NUM_SPLASH 40
967
+ #define FOUNTAIN_BASE vec2(0.0, -0.3)
968
+ #define WATER_LEVEL -0.3
969
+
970
+ void main() {
971
+ vec2 uv = (gl_FragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;
972
+ float t = iTime;
973
+
974
+ // Dark background
975
+ vec3 col = vec3(0.01, 0.02, 0.06);
976
+
977
+ // --- Water pool/surface ---
978
+ float waterDist = abs(uv.y - WATER_LEVEL);
979
+ float waterLine = smoothstep(0.01, 0.0, waterDist) * 0.3;
980
+ float waterBody = smoothstep(WATER_LEVEL, WATER_LEVEL - 0.15, uv.y);
981
+ col += vec3(0.02, 0.06, 0.12) * waterBody;
982
+ col += vec3(0.3, 0.5, 0.7) * waterLine;
983
+
984
+ // --- Main water column particles: upward jet + parabola ---
985
+ for (int i = 0; i < NUM_WATER; i++) {
986
+ float fi = float(i);
987
+ float lifetime = mix(1.0, 2.0, hash11(fi * 3.7));
988
+ float age = mod(t - hash11(fi * 2.3) * lifetime, lifetime);
989
+ float norm = age / lifetime;
990
+
991
+ float spreadAngle = (hash11(fi * 7.3) - 0.5) * 0.6;
992
+ float speed = mix(0.9, 1.6, hash11(fi * 11.0));
993
+ vec2 vel0 = vec2(sin(spreadAngle), cos(spreadAngle)) * speed;
994
+
995
+ vec2 pos = FOUNTAIN_BASE + vel0 * age + vec2(0.0, -1.8) * age * age;
996
+
997
+ if (pos.y < WATER_LEVEL - 0.02) continue;
998
+
999
+ vec2 rel = uv - pos;
1000
+ float dist = length(rel);
1001
+
1002
+ float fade = smoothstep(0.0, 0.05, norm) * smoothstep(1.0, 0.6, norm);
1003
+ // Sharp light point: small epsilon makes each particle clearly visible as an individual dot
1004
+ // peak = 0.004/0.0015 = 2.67, x 60 x avg_fade(0.25) ≈ 40 → Reinhard OK
1005
+ float glow = 0.004 / (dist * dist + 0.0015) * fade;
1006
+
1007
+ vec3 waterCol = mix(vec3(0.5, 0.8, 1.0), vec3(0.9, 0.97, 1.0), hash11(fi * 5.0));
1008
+ col += waterCol * glow;
1009
+ }
1010
+
1011
+ // --- Splash particles: spread sideways at water surface ---
1012
+ for (int i = 0; i < NUM_SPLASH; i++) {
1013
+ float fi = float(i) + 200.0;
1014
+ float lifetime = mix(0.3, 0.8, hash11(fi * 3.7));
1015
+ float age = mod(t - hash11(fi * 2.3) * lifetime, lifetime);
1016
+ float norm = age / lifetime;
1017
+
1018
+ float xOffset = (hash11(fi * 7.3) - 0.5) * 0.5;
1019
+ vec2 splashBase = vec2(xOffset, WATER_LEVEL);
1020
+ float splashAngle = (hash11(fi * 11.0) - 0.5) * 2.5;
1021
+ float splashSpeed = mix(0.2, 0.5, hash11(fi * 13.0));
1022
+ vec2 splashVel = vec2(sin(splashAngle), abs(cos(splashAngle))) * splashSpeed;
1023
+
1024
+ vec2 pos = splashBase + splashVel * age + vec2(0.0, -2.0) * age * age;
1025
+ if (pos.y < WATER_LEVEL - 0.01) continue;
1026
+
1027
+ vec2 rel = uv - pos;
1028
+ float dist = length(rel);
1029
+
1030
+ float fade = smoothstep(0.0, 0.05, norm) * smoothstep(1.0, 0.3, norm);
1031
+ float glow = 0.002 / (dist * dist + 0.001) * fade;
1032
+
1033
+ col += vec3(0.7, 0.85, 1.0) * glow;
1034
+ }
1035
+
1036
+ col = col / (1.0 + col);
1037
+ fragColor = vec4(col, 1.0);
1038
+ }
1039
+ ```
1040
+
1041
+ ### Variant 9: Campfire/Flame Particle System (Single-Pass Stateless)
1042
+
1043
+ Flame effects must include **two layers**: (1) smooth flame body at the base (noise-driven cone gradient) (2) many **discrete ember/spark particles** above, drifting upward and gradually extinguishing. Using only a smooth gradient will be judged as "no particle system."
1044
+
1045
+ **IMPORTANT: Most common flame failure**: Only draws a smooth gradient without discrete particles! Must have NUM_SPARKS individual point-like particles drifting out from the flame top.
1046
+
1047
+ ```glsl
1048
+ #define NUM_SPARKS 60
1049
+ #define FIRE_BASE vec2(0.0, -0.35)
1050
+
1051
+ float noise(vec2 p) {
1052
+ vec2 i = floor(p);
1053
+ vec2 f = fract(p);
1054
+ f = f * f * (3.0 - 2.0 * f);
1055
+ float a = hash11(dot(i, vec2(127.1, 311.7)));
1056
+ float b = hash11(dot(i + vec2(1.0, 0.0), vec2(127.1, 311.7)));
1057
+ float c = hash11(dot(i + vec2(0.0, 1.0), vec2(127.1, 311.7)));
1058
+ float d = hash11(dot(i + vec2(1.0, 1.0), vec2(127.1, 311.7)));
1059
+ return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
1060
+ }
1061
+
1062
+ void main() {
1063
+ vec2 uv = (gl_FragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;
1064
+ float t = iTime;
1065
+ vec3 col = vec3(0.02, 0.01, 0.01);
1066
+
1067
+ // --- Layer 1: flame body (smooth noise cone) ---
1068
+ vec2 fireUV = uv - FIRE_BASE;
1069
+ float fireH = clamp(fireUV.y / 0.5, 0.0, 1.0);
1070
+ float width = mix(0.15, 0.01, fireH);
1071
+ float n = noise(vec2(fireUV.x * 6.0, fireUV.y * 4.0 - t * 3.0));
1072
+ float flameShape = smoothstep(width, 0.0, abs(fireUV.x + (n - 0.5) * 0.08))
1073
+ * smoothstep(-0.02, 0.05, fireUV.y)
1074
+ * smoothstep(0.55, 0.0, fireUV.y);
1075
+ vec3 innerCol = vec3(1.0, 0.95, 0.7);
1076
+ vec3 outerCol = vec3(1.0, 0.35, 0.05);
1077
+ vec3 flameCol = mix(outerCol, innerCol, smoothstep(0.3, 0.8, flameShape));
1078
+ col += flameCol * flameShape * 1.5;
1079
+
1080
+ // --- Layer 2: discrete ember particles (required!) ---
1081
+ for (int i = 0; i < NUM_SPARKS; i++) {
1082
+ float fi = float(i);
1083
+ float lifetime = mix(0.8, 2.0, hash11(fi * 3.7));
1084
+ float age = mod(t - hash11(fi * 2.3) * lifetime, lifetime);
1085
+ float norm = age / lifetime;
1086
+
1087
+ float xSpread = (hash11(fi * 7.3) - 0.5) * 0.2;
1088
+ float riseSpeed = mix(0.3, 0.7, hash11(fi * 11.0));
1089
+ float wobble = sin(t * 3.0 + fi * 2.7) * 0.03 * norm;
1090
+ vec2 sparkPos = FIRE_BASE + vec2(0.0, 0.25)
1091
+ + vec2(xSpread + wobble, riseSpeed * age);
1092
+
1093
+ vec2 rel = uv - sparkPos;
1094
+ float dist = length(rel);
1095
+
1096
+ float fade = smoothstep(0.0, 0.1, norm) * smoothstep(1.0, 0.3, norm);
1097
+ // peak = 0.003/0.0008 = 3.75, x 60 x avg_fade(0.2) ≈ 45 → Reinhard OK
1098
+ float glow = 0.003 / (dist * dist + 0.0008) * fade;
1099
+
1100
+ float hue = mix(0.03, 0.12, norm);
1101
+ vec3 sparkCol = hsv2rgb(vec3(hue, mix(0.9, 0.3, norm), 1.0));
1102
+ col += sparkCol * glow;
1103
+ }
1104
+
1105
+ col = col / (1.0 + col);
1106
+ col = pow(col, vec3(0.95));
1107
+ fragColor = vec4(col, 1.0);
1108
+ }
1109
+ ```
1110
+
1111
+ ### Variant 10: Spiral Array/Magic Particle System (Single-Pass Stateless)
1112
+
1113
+ Magic effects, spiral ascent, magic circles, etc. require particles arranged in **geometric arrays** with **iridescent shimmer**. Key: particles must be individually visible glowing points (not a blurry glow blob), and the spiral structure must be clearly discernible.
1114
+
1115
+ **IMPORTANT: Most common magic failure**: Only produces a blob of blurry light (diffuse glow blob) without visible individual particles or geometric structure! Ensure each particle is an independently visible small light point, and the overall arrangement forms spiral/ring/other geometric shapes. Reduce epsilon to make each particle sharper (small light dot) rather than a large blurry halo.
1116
+
1117
+ ```glsl
1118
+ #define NUM_SPIRAL 80
1119
+ #define NUM_RING 40
1120
+ #define WAND_TIP vec2(0.0, -0.15)
1121
+
1122
+ void main() {
1123
+ vec2 uv = (gl_FragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;
1124
+ float t = iTime;
1125
+ vec3 col = vec3(0.01, 0.005, 0.02);
1126
+
1127
+ // --- Layer 1: spiral ascending particles (emanating from emission point) ---
1128
+ for (int i = 0; i < NUM_SPIRAL; i++) {
1129
+ float fi = float(i);
1130
+ float lifetime = mix(2.0, 4.0, hash11(fi * 3.7));
1131
+ float age = mod(t - hash11(fi * 2.3) * lifetime, lifetime);
1132
+ float norm = age / lifetime;
1133
+
1134
+ // Spiral trajectory: angle increases with time and height
1135
+ float baseAngle = fi / float(NUM_SPIRAL) * 6.2832 * 3.0;
1136
+ float spiralAngle = baseAngle + norm * 8.0 + t * 1.5;
1137
+ float radius = 0.05 + norm * 0.25;
1138
+ float height = norm * 0.7;
1139
+
1140
+ vec2 pos = WAND_TIP + vec2(cos(spiralAngle) * radius, height);
1141
+
1142
+ vec2 rel = uv - pos;
1143
+ float dist = length(rel);
1144
+
1145
+ float fade = smoothstep(0.0, 0.08, norm) * smoothstep(1.0, 0.4, norm);
1146
+ // Sharp small light point: small epsilon makes particles clearly visible as individual dots
1147
+ // peak = 0.004/0.0006 = 6.67, x 80 x avg_fade(0.25) ≈ 133 → Reinhard OK
1148
+ float glow = 0.004 / (dist * dist + 0.0006) * fade;
1149
+
1150
+ // Iridescent effect: hue varies with particle ID + time, producing rainbow shimmer
1151
+ float hue = fract(fi / float(NUM_SPIRAL) + t * 0.3 + norm * 0.5);
1152
+ float shimmer = 0.7 + 0.3 * sin(t * 8.0 + fi * 3.7);
1153
+ vec3 pCol = hsv2rgb(vec3(hue, 0.7, 1.0)) * shimmer;
1154
+ col += pCol * glow;
1155
+ }
1156
+
1157
+ // --- Layer 2: magic circle ring (horizontally rotating light point ring) ---
1158
+ float ringY = WAND_TIP.y + 0.45;
1159
+ float ringRadius = 0.2 + 0.03 * sin(t * 2.0);
1160
+ for (int i = 0; i < NUM_RING; i++) {
1161
+ float fi = float(i);
1162
+ float angle = fi / float(NUM_RING) * 6.2832 + t * 2.0;
1163
+ // Simulated perspective: ellipse (cos full width, sin compressed)
1164
+ vec2 ringPos = vec2(cos(angle) * ringRadius, ringY + sin(angle) * ringRadius * 0.3);
1165
+
1166
+ vec2 rel = uv - ringPos;
1167
+ float dist = length(rel);
1168
+
1169
+ float pulse = 0.6 + 0.4 * sin(t * 5.0 + fi * 1.5);
1170
+ // peak = 0.003/0.0004 = 7.5, x 40 x avg_pulse(0.6) ≈ 180 → Reinhard OK
1171
+ float glow = 0.003 / (dist * dist + 0.0004) * pulse;
1172
+
1173
+ float hue = fract(fi / float(NUM_RING) + t * 0.5);
1174
+ vec3 rCol = hsv2rgb(vec3(hue, 0.6, 1.0));
1175
+ col += rCol * glow;
1176
+ }
1177
+
1178
+ col = col / (1.0 + col);
1179
+ col = pow(col, vec3(0.9));
1180
+ fragColor = vec4(col, 1.0);
1181
+ }
1182
+ ```
1183
+
1184
+ ## Performance & Composition
1185
+
1186
+ **Performance**:
1187
+ - Particle count is the biggest performance lever; use early exit `if (dist > threshold) continue;` for optimization
1188
+ - Frame feedback trails (`prev * 0.95 + current`) can achieve high visual density with fewer particles
1189
+ - N-body O(N²) interaction: reduce to O(1) neighbor queries using spatial grid partitioning or Voronoi tracking
1190
+ - High-speed particles use sub-frame stepping to eliminate trajectory gaps
1191
+ - Velocity/acceleration need clamp to prevent numerical explosion; Verlet is more stable than Euler
1192
+ -
1193
+
1194
+ **Composition**:
1195
+ - **Raymarching**: sample particle density during march steps, or particles in separate Buffer then composited
1196
+ - **Noise / Flow Field**: use noise gradients to drive particle velocity, producing organic flow effects
1197
+ - **Post-Processing**: Bloom (Gaussian blur overlay), chromatic aberration, Reinhard tone mapping
1198
+ - **SDF shapes**: rotate local coordinates based on velocity direction to render fish/droplet specific shapes
1199
+ - **Voronoi acceleration**: large-scale particles use Voronoi tracking, reducing rendering and physics queries from O(N) to O(1)
1200
+
1201
+ ## Further Reading
1202
+
1203
+ Full step-by-step tutorial, mathematical derivations, and advanced usage in [reference](../reference/particle-system.md)