From 201c229dcb70e5854a58bdcae85a25050aca834f Mon Sep 17 00:00:00 2001 From: Pinkesh Date: Wed, 20 May 2026 11:21:32 +0530 Subject: [PATCH] Add Shadertoy integration guide to shaders docs --- .../animations/imgs/convert-via-url.avif | Bin 0 -> 30019 bytes docs/ff-concepts/animations/shaders.md | 172 +++++++++++++++++- 2 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 docs/ff-concepts/animations/imgs/convert-via-url.avif diff --git a/docs/ff-concepts/animations/imgs/convert-via-url.avif b/docs/ff-concepts/animations/imgs/convert-via-url.avif new file mode 100644 index 0000000000000000000000000000000000000000..817ede4e5be625d6f7cf4a8fc21f1d97bd46fcfd GIT binary patch literal 30019 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 OuTGvk75>*fch10&3@_UN literal 0 HcmV?d00001 diff --git a/docs/ff-concepts/animations/shaders.md b/docs/ff-concepts/animations/shaders.md index 7895499e..a9896a06 100644 --- a/docs/ff-concepts/animations/shaders.md +++ b/docs/ff-concepts/animations/shaders.md @@ -414,4 +414,174 @@ uniform float uTime; uniform float speed; uniform vec4 color; -``` \ No newline at end of file +``` + +## Use Shadertoy Shaders + +[Shadertoy](https://www.shadertoy.com/) hosts thousands of community-made GLSL fragment shaders such as animated backgrounds, glowing effects, liquid simulations, and more. Flutter supports custom fragment shaders through its `FragmentProgram` API, but Shadertoy shaders can't be dropped in directly: they use a different entry point, different uniform names, and several built-ins that Flutter doesn't recognize. + +The [Shadertoy to Flutter skill](https://github.com/FlutterFlow/shadertoy_to_flutter_skill) helps convert Shadertoy GLSL into Flutter-compatible `.frag` shaders. It rewrites the shader structure, maps Shadertoy uniforms to Flutter uniforms, handles texture/audio channels where possible, and produces a `.frag` file that can be uploaded into your FlutterFlow project. + +#### Step 1: Download Skill + +The skill teaches AI Agents how to convert Shadertoy shaders accurately and safely for Flutter. The skill used for this workflow is: **`shadertoy-to-flutter`**. Download it from the [GitHub repo](https://github.com/FlutterFlow/shadertoy_to_flutter_skill). + +The skill contains the following files: + +- `SKILL.md`: Main instruction file containing the shader conversion workflow and rules. +- `references/flutter_glsl_constraints.md`: Flutter GLSL limitations, unsupported features, uniform rules, and texture handling. +- `references/uniform_mapping.md`: Maps Shadertoy uniforms to Flutter equivalents (e.g. `iTime → uTime`). +- `references/templates.md`: Example fill/wrap shader templates and sample conversions. +- `references/noise_library.md`: Noise/hash helper functions for replacing Shadertoy noise textures. +- `scripts/package-skill.sh`: Packages the skill into a distributable zip file. + +#### Step 2: Install Skill + +You can use this skill with AI agents such as Claude, Codex, or another AI assistant that can read `SKILL.md` and follow its instructions. + +**Install in Claude** + +1. Open the **Claude Desktop app**. +2. Go to **Customize**. Select **Skills** from the left sidebar. +3. Click the **+** button at the top of the Skills panel. Choose **Upload a skill**. +4. Upload the Shadertoy skill as a .zip file or skill folder. + +The uploaded skill must include:`SKILL.md`. It can also include supporting folders such as: `references/` and `scripts/` + +
+ +
+

+ +**Install in Codex** + +1. Open the **Codex Desktop app**. +2. In the message box, type: `/sk` +3. Select **Skill Installer** from the skill suggestions list. +4. Ask Codex to install the Shadertoy skill directly from GitHub: + +``` +Install this skill https://github.com/FlutterFlow/shadertoy_to_flutter_skill +``` + +Codex will run the Skill Installer and install the skill into your local Codex folder. After installation finishes, restart Codex. + +
+ +
+

+ +#### Step 3: Using Skill + +You can use the skill with either a Shadertoy URL or a local .glsl file. + +**Option A: Convert a Shadertoy URL** + +In the prompt, provide the Shadertoy URL and ask to convert into `.frag` file, for example: + +``` +[invoke shadertoy-to-flutter skill] convert this Shadertoy shader into a Flutter .frag file: +[shadertoy-url] +``` + +![convert-via-url.avif](imgs/convert-via-url.avif) + +**Option B: Convert a Local .glsl File** + +Open the Shadertoy shader you want to use, copy the shader code, and save it as a `.glsl` file. Then attach the file and use a prompt such as: + +``` +[invoke shadertoy-to-flutter skill] convert this file into a Flutter .frag file +``` + +
+ +
+

+ +:::tip + +You can also paste the shader code directly into the prompt, for example: + +``` +Use the /shadertoy-to-flutter skill and convert this shader to a Flutter .frag file: + +[paste shader code] +``` + +::: + +#### Step 4: Upload .frag File to FlutterFlow Project + +Upload the `.frag` file generated in the previous step to the **Shader Asset** picker in FlutterFlow and run your app. If required, also [add Uniform](#adding-uniforms) to define input values for your shader. + +### Best Practices + +- Keep the generated .frag file unchanged unless you know GLSL well. +- Always check the uniform order before wiring values in FlutterFlow or Dart. +- Prefer fill shaders when possible because they are easier to use. +- Use wrap shaders only when the shader needs an image, scene, or app UI texture. +- Avoid adding extra uniforms unless you really need user control. \ No newline at end of file