├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── build.md
│ ├── chore.md
│ ├── ci.md
│ ├── config.yml
│ ├── documentation.md
│ ├── feature_request.md
│ ├── performance.md
│ ├── refactor.md
│ ├── revert.md
│ ├── style.md
│ └── test.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .metadata
├── .vscode
├── launch.json
└── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── assets
└── blank_16x16.bmp
├── example
├── .gitignore
├── .metadata
├── README.md
├── analysis_options.yaml
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle.kts
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── shader_buffers_example
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ │ ├── drawable-v21
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── values-night
│ │ │ │ └── styles.xml
│ │ │ │ └── values
│ │ │ │ └── styles.xml
│ │ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── build.gradle.kts
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle.kts
├── assets
│ ├── bricks.jpg
│ ├── flutter.png
│ ├── noise.png
│ ├── noise_color.png
│ └── shaders
│ │ ├── arrows.frag
│ │ ├── common
│ │ ├── common_header.frag
│ │ └── main_shadertoy.frag
│ │ ├── filters
│ │ ├── black.frag
│ │ └── white.frag
│ │ ├── mouse1.frag
│ │ ├── mouse2.frag
│ │ ├── noise_fade.frag
│ │ ├── page_curl.frag
│ │ ├── ripple.frag
│ │ ├── shader1_bufferA.frag
│ │ ├── shader1_main.frag
│ │ ├── shader2_bufferA.frag
│ │ ├── shader2_main.frag
│ │ ├── test.frag
│ │ ├── test_isself_buffer_a.frag
│ │ ├── test_isself_main.frag
│ │ └── water.frag
├── example.md
├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ ├── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ │ └── LaunchImage.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ └── README.md
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ └── Runner-Bridging-Header.h
│ └── RunnerTests
│ │ └── RunnerTests.swift
├── lib
│ ├── main.dart
│ └── simple_layers.dart
├── linux
│ ├── .gitignore
│ ├── CMakeLists.txt
│ ├── flutter
│ │ ├── CMakeLists.txt
│ │ ├── generated_plugin_registrant.cc
│ │ ├── generated_plugin_registrant.h
│ │ └── generated_plugins.cmake
│ ├── main.cc
│ ├── my_application.cc
│ └── my_application.h
├── macos
│ ├── .gitignore
│ ├── Flutter
│ │ ├── Flutter-Debug.xcconfig
│ │ ├── Flutter-Release.xcconfig
│ │ └── GeneratedPluginRegistrant.swift
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── app_icon_1024.png
│ │ │ │ ├── app_icon_128.png
│ │ │ │ ├── app_icon_16.png
│ │ │ │ ├── app_icon_256.png
│ │ │ │ ├── app_icon_32.png
│ │ │ │ ├── app_icon_512.png
│ │ │ │ └── app_icon_64.png
│ │ ├── Base.lproj
│ │ │ └── MainMenu.xib
│ │ ├── Configs
│ │ │ ├── AppInfo.xcconfig
│ │ │ ├── Debug.xcconfig
│ │ │ ├── Release.xcconfig
│ │ │ └── Warnings.xcconfig
│ │ ├── DebugProfile.entitlements
│ │ ├── Info.plist
│ │ ├── MainFlutterWindow.swift
│ │ └── Release.entitlements
│ └── RunnerTests
│ │ └── RunnerTests.swift
├── pubspec.lock
├── pubspec.yaml
├── web
│ ├── favicon.png
│ ├── icons
│ │ ├── Icon-192.png
│ │ ├── Icon-512.png
│ │ ├── Icon-maskable-192.png
│ │ └── Icon-maskable-512.png
│ ├── index.html
│ └── manifest.json
└── windows
│ ├── .gitignore
│ ├── CMakeLists.txt
│ ├── flutter
│ ├── CMakeLists.txt
│ ├── generated_plugin_registrant.cc
│ ├── generated_plugin_registrant.h
│ └── generated_plugins.cmake
│ └── runner
│ ├── CMakeLists.txt
│ ├── Runner.rc
│ ├── flutter_window.cpp
│ ├── flutter_window.h
│ ├── main.cpp
│ ├── resource.h
│ ├── resources
│ └── app_icon.ico
│ ├── runner.exe.manifest
│ ├── utils.cpp
│ ├── utils.h
│ ├── win32_window.cpp
│ └── win32_window.h
├── images
└── shader_buffers.gif
├── lib
├── shader_buffers.dart
└── src
│ ├── custom_child.dart
│ ├── custom_shader_paint.dart
│ ├── i_channel.dart
│ ├── imouse.dart
│ ├── layer_buffer.dart
│ ├── shader_buffers.dart
│ └── uniforms.dart
├── pubspec.yaml
└── test
└── shader_buffers_test.dart
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug Report
3 | about: Create a report to help us improve
4 | title: "fix: "
5 | labels: bug
6 | ---
7 |
8 | **Description**
9 |
10 | A clear and concise description of what the bug is.
11 |
12 | **Steps To Reproduce**
13 |
14 | 1. Go to '...'
15 | 2. Click on '....'
16 | 3. Scroll down to '....'
17 | 4. See error
18 |
19 | **Expected Behavior**
20 |
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 |
25 | If applicable, add screenshots to help explain your problem.
26 |
27 | **Additional Context**
28 |
29 | Add any other context about the problem here.
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/build.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Build System
3 | about: Changes that affect the build system or external dependencies
4 | title: "build: "
5 | labels: build
6 | ---
7 |
8 | **Description**
9 |
10 | Describe what changes need to be done to the build system and why.
11 |
12 | **Requirements**
13 |
14 | - [ ] The build system is passing
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/chore.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Chore
3 | about: Other changes that don't modify src or test files
4 | title: "chore: "
5 | labels: chore
6 | ---
7 |
8 | **Description**
9 |
10 | Clearly describe what change is needed and why. If this changes code then please use another issue type.
11 |
12 | **Requirements**
13 |
14 | - [ ] No functional changes to the code
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/ci.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Continuous Integration
3 | about: Changes to the CI configuration files and scripts
4 | title: "ci: "
5 | labels: ci
6 | ---
7 |
8 | **Description**
9 |
10 | Describe what changes need to be done to the ci/cd system and why.
11 |
12 | **Requirements**
13 |
14 | - [ ] The ci system is passing
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/documentation.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Documentation
3 | about: Improve the documentation so all collaborators have a common understanding
4 | title: "docs: "
5 | labels: documentation
6 | ---
7 |
8 | **Description**
9 |
10 | Clearly describe what documentation you are looking to add or improve.
11 |
12 | **Requirements**
13 |
14 | - [ ] Requirements go here
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature Request
3 | about: A new feature to be added to the project
4 | title: "feat: "
5 | labels: feature
6 | ---
7 |
8 | **Description**
9 |
10 | Clearly describe what you are looking to add. The more context the better.
11 |
12 | **Requirements**
13 |
14 | - [ ] Checklist of requirements to be fulfilled
15 |
16 | **Additional Context**
17 |
18 | Add any other context or screenshots about the feature request go here.
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/performance.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Performance Update
3 | about: A code change that improves performance
4 | title: "perf: "
5 | labels: performance
6 | ---
7 |
8 | **Description**
9 |
10 | Clearly describe what code needs to be changed and what the performance impact is going to be. Bonus point's if you can tie this directly to user experience.
11 |
12 | **Requirements**
13 |
14 | - [ ] There is no drop in test coverage.
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/refactor.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Refactor
3 | about: A code change that neither fixes a bug nor adds a feature
4 | title: "refactor: "
5 | labels: refactor
6 | ---
7 |
8 | **Description**
9 |
10 | Clearly describe what needs to be refactored and why. Please provide links to related issues (bugs or upcoming features) in order to help prioritize.
11 |
12 | **Requirements**
13 |
14 | - [ ] There is no drop in test coverage.
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/revert.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Revert Commit
3 | about: Reverts a previous commit
4 | title: "revert: "
5 | labels: revert
6 | ---
7 |
8 | **Description**
9 |
10 | Provide a link to a PR/Commit that you are looking to revert and why.
11 |
12 | **Requirements**
13 |
14 | - [ ] Change has been reverted
15 | - [ ] No change in test coverage has happened
16 | - [ ] A new ticket is created for any follow on work that needs to happen
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/style.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Style Changes
3 | about: Changes that do not affect the meaning of the code (white space, formatting, missing semi-colons, etc)
4 | title: "style: "
5 | labels: style
6 | ---
7 |
8 | **Description**
9 |
10 | Clearly describe what you are looking to change and why.
11 |
12 | **Requirements**
13 |
14 | - [ ] There is no drop in test coverage.
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/test.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Test
3 | about: Adding missing tests or correcting existing tests
4 | title: "test: "
5 | labels: test
6 | ---
7 |
8 | **Description**
9 |
10 | List out the tests that need to be added or changed. Please also include any information as to why this was not covered in the past.
11 |
12 | **Requirements**
13 |
14 | - [ ] There is no drop in test coverage.
15 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
8 |
9 | ## Description
10 |
11 |
12 |
13 | ## Type of Change
14 |
15 |
16 |
17 | - [ ] ✨ New feature (non-breaking change which adds functionality)
18 | - [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
19 | - [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
20 | - [ ] 🧹 Code refactor
21 | - [ ] ✅ Build configuration change
22 | - [ ] 📝 Documentation
23 | - [ ] 🗑️ Chore
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
26 | /pubspec.lock
27 | **/doc/api/
28 | .dart_tool/
29 | .packages
30 | build/
31 |
32 | images/*
33 | !images/shader_buffers.gif
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: "d211f42860350d914a5ad8102f9ec32764dc6d06"
8 | channel: "stable"
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "example",
9 | "cwd": "example",
10 | "request": "launch",
11 | "type": "dart"
12 | },
13 | {
14 | "name": "example (profile mode)",
15 | "cwd": "example",
16 | "request": "launch",
17 | "type": "dart",
18 | "flutterMode": "profile"
19 | },
20 | {
21 | "name": "example (release mode)",
22 | "cwd": "example",
23 | "request": "launch",
24 | "type": "dart",
25 | "flutterMode": "release"
26 | },
27 | {
28 | "name": "Simple Layer example",
29 | "type": "dart",
30 | "request": "launch",
31 | "program": "lib/simple_layers.dart",
32 | "flutterMode": "debug",
33 | "cwd": "${workspaceFolder}/example"
34 | },
35 | ]
36 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cmake.sourceDirectory": "/home/deimos/FLUTTER/libs/shader_buffers/example/linux"
3 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 1.1.2
2 | - properly dispose ShaderBuffers
3 |
4 | ## 1.1.1
5 | - added `onShaderLoaded' callback to `ShaderBuffers`
6 | - fix the issue with the get of devicePixelRatio which caused a black widget.
7 |
8 | ## 1.1.0
9 | - fix Low Rendering Quality Issue #7
10 | - added `scaleRenderView` to `LayerBuffer` to compute the shader to a scaled resolution compared to the widget size.
11 |
12 | ## 1.0.1
13 | - fix GIF link in README
14 |
15 | ## 1.0.0
16 | - Initial release.
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **shader_buffers** aims to simplify the use of shaders with a focus on the ShaderToy.com
2 |
3 | [](https://pub.dev/packages/shader_buffers)
4 |
5 | - [Features](#Features)
6 | - [ShaderBuffers widget Usage](#ShaderBuffers-widget-Usage)
7 | - [User interaction](#User-interaction)
8 | - [Add simple check value operations](#Add-simple-check-value-operations)
9 | - [Layering shaders](#Layering-shaders)
10 | - [Additional information](#Additional-information)
11 | - [Writing a fragment shader](#Writing-a-fragment-shader)
12 |
13 | ## Features
14 |
15 |
16 | - [x] Use shader output to feed other shader textures.
17 | - [x] Feed shaders with asset images or any widgets as `sampler2D uniforms`.
18 | - [x] Capture user interaction.
19 | - [x] Easily add custom uniforms.
20 | - [x] Animate custom uniforms.
21 | - [x] Play / Pause / Rewind shader.
22 | - [x] Conditional operations to check mouse/tap position, time, frame number, and custom uniforms.
23 |
24 | ***Please***, take a look at the [shader_presets](https://github.com/alnitak/shader_presets) package which implements some ready-to-use shaders, like transitions and effects (from [gl-transitions](https://gl-transitions.com/) and [ShaderToy](https://www.shadertoy.com/)).
25 |
26 | Tested on Android, Linux and web, it should work on other desktops.
27 | Seems that impeller engine is not yet ready, on iOS it should work with [impeller disabled](https://docs.flutter.dev/perf/impeller#ios).
28 | Shader examples are from [ShaderToy.com](https://shadertoy.com) and have been slightly modified. Credits links are in the main shaders sources.
29 |
30 | > [!NOTE]
31 | > Using a shader output to feed itself, produces a memory leak: [memory leak issue](https://github.com/flutter/flutter/issues/138627). Please thumb it up! A temporary fix is used.
32 |
33 | 
34 |
35 |
36 | ## ShaderBuffers widget Usage
37 |
38 | The main widget to use is `ShaderBuffers`, which takes its size and `mainImage` as input. Optionally, you can add the `buffers`.
39 |
40 | `mainImage` and `buffers` are of type `LayerBuffer`, which defines the fragment shader asset source and the texture channels.
41 |
42 | `mainImage` shader must be provided. The more `buffers`, the more performances will be affected.
43 | Think of `mainImage` as the *Image* layer fragment in ShaderToy.com and `buffers` as *Buffer[A-D]*.
44 |
45 | Each frame buffers are computed from the 1st to the last, then `mainImage`.
46 |
47 | This widget provides the following uniforms to the fragment shader:
48 | * `sampler2D iChannel[0-N]` as many as defined in `LayerBuffer.channels`
49 | * `vec2 iResolution` the widget width and height
50 | * `float iTime` the current time in seconds from the start of rendering
51 | * `float iFrame` the current rendering frame number
52 | * `vec4 iMouse` for user interaction with pointer (see `IMouse`)
53 |
54 | To start, you can define the layers:
55 | ```dart
56 |
57 | /// The main layer uses `shader_main.frag` as a fragment shader source and some float uniforms
58 | final mainImage = LayerBuffer(
59 | shaderAssetsName: 'assets/shaders/shader_main.glsl',
60 | uniforms: Uniforms([
61 | Uniform(
62 | name: 'blur',
63 | range: const RangeValues(0, 1),
64 | defaultValue: 0.9,
65 | value: 0.9,
66 | ),
67 | Uniform(
68 | name: 'velocity',
69 | range: const RangeValues(0, 1),
70 | defaultValue: 0.2,
71 | value: 0.2,
72 | ),
73 | ]),
74 | );
75 | ```
76 | Now you can use `ShaderBuffers`:
77 | ```dart
78 | ShaderController controller = ShaderController();
79 | ShaderBuffers(
80 | controller: controller,
81 | mainImage: mainImage,
82 | )
83 | ```
84 |
85 | `mainImage` and `buffers` are of type `IChannel`. The latter represents the `uniform sampler2D` texture to be passed to the *fragment shader*.
86 |
87 | #### User interaction
88 | **ShaderBuffers** listen to the pointer with *onPointerDown*, *onPointerMove*, *onPointerUp* which give back the controller and the position in pixels. Most of the time is more useful to have back the normalized position (in the 0~1 range) instead of pixels. This can be achieved with *onPointerDownNormalized*, *onPointerMoveNormalized*, *onPointerUpNormalized* callbacks.
89 | With the *controller*, the one passed to *ShaderBuffers*, or the one returned by the *onPointer** callbacks, is possible to do these:
90 | - play
91 | - pause
92 | - rewind
93 | - getState
94 | - getImouse
95 | - getImouseNormalized
96 |
97 | #### Add simple check value operations
98 | It's possible to check for some conditions.
99 | - a condition is bonded to a given ***LayerBuffer***.
100 | - the ***param*** could be:*iMouseX*, *iMouseY*, *iMouseXNormalized*, *iMouseYNormalized*, *iTime*, *iFrame*
101 | - ***checkType*** could be: *minor*, *major*, *equal*
102 | - ***checkValue*** is the value to check
103 | - ***operation*** is the callback that returns true of false based on the resulting check
104 |
105 |
106 | ```dart
107 | controller
108 | ..addConditionalOperation(
109 | (
110 | layerBuffer: mainImage,
111 | param: Param.iMouseXNormalized,
112 | checkType: CheckOperator.minor,
113 | checkValue: 0.5,
114 | operation: (result) {
115 | /// [result] == true means (iMouseXNormalized < 0.5 )
116 | },
117 | ),
118 | )
119 | ```
120 |
121 | #### Layering shaders
122 |
123 |
124 |
125 | ```dart
126 | final mainLayer = LayerBuffer(
127 | shaderAssetsName: 'assets/shaders/shader_main.frag',
128 | );
129 | final bufferA = LayerBuffer(
130 | shaderAssetsName: 'assets/shaders/shader_bufferA.frag',
131 | );
132 | final bufferB = LayerBuffer(
133 | shaderAssetsName: 'assets/shaders/shader_bufferB.frag',
134 | );
135 | final bufferC = LayerBuffer(
136 | shaderAssetsName: 'assets/shaders/shader_bufferC.frag',
137 | );
138 | mainLayer.setChannels([IChannel(buffer: bufferC)]);
139 | bufferB.setChannels([IChannel(buffer: bufferA)]);
140 | bufferC.setChannels([
141 | IChannel(buffer: bufferA),
142 | IChannel(buffer: bufferB),
143 | IChannel(assetsTexturePath: 'assets/bricks.jpg'),
144 | ]);
145 | ```
146 |
147 |
148 | ## Additional information
149 |
150 | The main drawback when willing to port ShaderToy shader buffers is that they use 4 floats per RGBA channel, while with Flutter shader we are stuck using 4 int8 RGBA.
151 | Also, the coordinate system is slightly different: the origin in ShaderToy is *bottom-left* while in Flutter, is *top-left*. This latter issue can be easily bypassed where in the main image layer you see this:
152 | `vec2 uv = fragCoord.xy / iResolution.xy;`
153 | after this line, you can add this to swap Y coordinates:
154 | `uv = vec2(uv.x, 1. - uv.y);`
155 |
156 | #### Writing a fragment shader
157 |
158 | It's mandatory to provide the shader the following `uniforms` since **shader_buffer** always sends them:
159 |
160 | ```
161 | uniform vec2 iResolution;
162 | uniform float iTime;
163 | uniform float iFrame;
164 | uniform vec4 iMouse;
165 | ```
166 |
167 | For simplicity, there is `assets/shader/common/common_header.frag` to include at the very beginning of the shader:
168 | `#include `
169 |
170 | it provides also:
171 | `out vec4 fragColor;`
172 |
173 | If you are experimenting with ShaderToy shaders, start your code copied from it and at the bottom of the file include `main_shadertoy.frag`:
174 | `#include `
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:very_good_analysis/analysis_options.yaml
2 |
--------------------------------------------------------------------------------
/assets/blank_16x16.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/assets/blank_16x16.bmp
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Symbolication related
36 | app.*.symbols
37 |
38 | # Obfuscation related
39 | app.*.map.json
40 |
41 | # Android Studio will place build artifacts here
42 | /android/app/debug
43 | /android/app/profile
44 | /android/app/release
45 |
--------------------------------------------------------------------------------
/example/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: "05db9689081f091050f01aed79f04dce0c750154"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 05db9689081f091050f01aed79f04dce0c750154
17 | base_revision: 05db9689081f091050f01aed79f04dce0c750154
18 | - platform: android
19 | create_revision: 05db9689081f091050f01aed79f04dce0c750154
20 | base_revision: 05db9689081f091050f01aed79f04dce0c750154
21 |
22 | # User provided section
23 |
24 | # List of Local paths (relative to this file) that should be
25 | # ignored by the migrate tool.
26 | #
27 | # Files that are not part of the templates will be ignored by default.
28 | unmanaged_files:
29 | - 'lib/main.dart'
30 | - 'ios/Runner.xcodeproj/project.pbxproj'
31 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # example
2 |
3 | A new Flutter project.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
13 |
14 | For help getting started with Flutter development, view the
15 | [online documentation](https://docs.flutter.dev/), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/example/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:very_good_analysis/analysis_options.yaml
2 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 | .cxx/
9 |
10 | # Remember to never publicly share your keystore.
11 | # See https://flutter.dev/to/reference-keystore
12 | key.properties
13 | **/*.keystore
14 | **/*.jks
15 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | id("kotlin-android")
4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5 | id("dev.flutter.flutter-gradle-plugin")
6 | }
7 |
8 | android {
9 | namespace = "com.example.shader_buffers_example"
10 | compileSdk = flutter.compileSdkVersion
11 | ndkVersion = flutter.ndkVersion
12 |
13 | compileOptions {
14 | sourceCompatibility = JavaVersion.VERSION_11
15 | targetCompatibility = JavaVersion.VERSION_11
16 | }
17 |
18 | kotlinOptions {
19 | jvmTarget = JavaVersion.VERSION_11.toString()
20 | }
21 |
22 | defaultConfig {
23 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
24 | applicationId = "com.example.shader_buffers_example"
25 | // You can update the following values to match your application needs.
26 | // For more information, see: https://flutter.dev/to/review-gradle-config.
27 | minSdk = flutter.minSdkVersion
28 | targetSdk = flutter.targetSdkVersion
29 | versionCode = flutter.versionCode
30 | versionName = flutter.versionName
31 | }
32 |
33 | buildTypes {
34 | release {
35 | // TODO: Add your own signing config for the release build.
36 | // Signing with the debug keys for now, so `flutter run --release` works.
37 | signingConfig = signingConfigs.getByName("debug")
38 | }
39 | }
40 | }
41 |
42 | flutter {
43 | source = "../.."
44 | }
45 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/example/shader_buffers_example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.shader_buffers_example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity : FlutterActivity()
6 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/build.gradle.kts:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | val newBuildDir: Directory =
9 | rootProject.layout.buildDirectory
10 | .dir("../../build")
11 | .get()
12 | rootProject.layout.buildDirectory.value(newBuildDir)
13 |
14 | subprojects {
15 | val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
16 | project.layout.buildDirectory.value(newSubprojectBuildDir)
17 | }
18 | subprojects {
19 | project.evaluationDependsOn(":app")
20 | }
21 |
22 | tasks.register("clean") {
23 | delete(rootProject.layout.buildDirectory)
24 | }
25 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
6 |
--------------------------------------------------------------------------------
/example/android/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | val flutterSdkPath =
3 | run {
4 | val properties = java.util.Properties()
5 | file("local.properties").inputStream().use { properties.load(it) }
6 | val flutterSdkPath = properties.getProperty("flutter.sdk")
7 | require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
8 | flutterSdkPath
9 | }
10 |
11 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
12 |
13 | repositories {
14 | google()
15 | mavenCentral()
16 | gradlePluginPortal()
17 | }
18 | }
19 |
20 | plugins {
21 | id("dev.flutter.flutter-plugin-loader") version "1.0.0"
22 | id("com.android.application") version "8.9.1" apply false
23 | id("org.jetbrains.kotlin.android") version "2.1.0" apply false
24 | }
25 |
26 | include(":app")
27 |
--------------------------------------------------------------------------------
/example/assets/bricks.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/assets/bricks.jpg
--------------------------------------------------------------------------------
/example/assets/flutter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/assets/flutter.png
--------------------------------------------------------------------------------
/example/assets/noise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/assets/noise.png
--------------------------------------------------------------------------------
/example/assets/noise_color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/assets/noise_color.png
--------------------------------------------------------------------------------
/example/assets/shaders/arrows.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | // credits:
4 | // https://www.shadertoy.com/view/Nty3Wm
5 |
6 | // ------ START SHADERTOY CODE -----
7 | #define pi 3.14159
8 |
9 | float thc(float a, float b) {
10 | return tanh(a * cos(b)) / tanh(a);
11 | }
12 |
13 | // square length
14 | float mlength(vec2 uv) {
15 | return max(abs(uv.x), abs(uv.y));
16 | }
17 |
18 | vec2 rot(vec2 uv, float a) {
19 | mat2 mat = mat2(cos(a), -sin(a),
20 | sin(a), cos(a));
21 | return mat * uv;
22 | }
23 |
24 | float sdEquilateralTriangle( in vec2 p )
25 | {
26 | const float k = sqrt(3.0);
27 | p.x = abs(p.x) - 1.0;
28 | p.y = p.y + 1.0/k;
29 | if( p.x+k*p.y>0.0 ) p = vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
30 | p.x -= clamp( p.x, -2.0, 0.0 );
31 | return -length(p)*sign(p.y);
32 | }
33 |
34 | float sdBox( in vec2 p, in vec2 b )
35 | {
36 | vec2 d = abs(p)-b;
37 | return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
38 | }
39 |
40 | // draws an arrow (d is used to make it go up + down)
41 | float arrow(vec2 uv, float d) {
42 | float h = 0.1 + 0.4 * thc(4.,2. * d);
43 | float d1 = sdEquilateralTriangle(uv-vec2(0.,0.25 - h));
44 | float s1 = step(d1, -0.5);
45 |
46 | float d2 = sdBox(uv - vec2(0.,-h), vec2(0.05,0.2));
47 | float s2 = step(d2, 0.);
48 |
49 | return max(s1, s2);
50 | }
51 |
52 | vec3 pal( in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d )
53 | {
54 | return a + b*cos( 6.28318*(c*t+d) );
55 | }
56 |
57 |
58 | void mainImage( out vec4 fragColor, in vec2 fragCoord )
59 | {
60 | vec2 uv = (fragCoord-0.5*iResolution.xy)/iResolution.y;
61 |
62 | // scale (number of arrows)
63 | float sc = 10.;
64 | vec2 ipos = floor(sc * uv) + 0.5;
65 | ipos /= sc;
66 | vec2 fpos = fract(sc * uv) - 0.5;
67 |
68 | vec2 p = (iMouse.xy-0.5*iResolution.xy)/iResolution.y;
69 |
70 | // moving point
71 | // p = 0.4 * vec2(iResolution.x/iResolution.y * thc(2., 0.5 * iTime), sin(iTime));
72 |
73 | // cursor
74 | float d2 = length(uv-p);
75 | float s2 = step(d2,0.02) - step(d2,0.016);
76 | s2 *= 0.5;
77 |
78 | // grid
79 | float d3 = mlength(fpos);
80 | float s3 = step(d3,0.5) - step(d3,0.48);
81 | s3 *= 0.2;
82 |
83 | // change me!
84 | float n = 1.;
85 | // n = -3.;
86 |
87 | // rotate arrows towards cursor
88 | float th = -0.5 * pi + n * atan(p.y-ipos.y, p.x-ipos.x);
89 | fpos = rot(fpos, th);
90 |
91 | // shrink arrows that are far away
92 | fpos *= 1. + d2 * d2;
93 |
94 | // arrow
95 | float s1 = 0.5 * arrow(fpos, d2) ;
96 |
97 | float s = max(max(s1,s2), s3);
98 |
99 | // fade
100 | // s *= pow(1.-length(ipos-p),3.);
101 |
102 | vec3 e = vec3(1.);
103 | vec3 col = s * pal(s3 * th + d2 - 0.4 * iTime, e, e, e, vec3(0.,1., 2.)/3.);
104 | // col = vec3(s);
105 |
106 | fragColor = vec4(col,1.0);
107 | }
108 | // ------ END SHADERTOY CODE -----
109 |
110 |
111 |
112 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/common/common_header.frag:
--------------------------------------------------------------------------------
1 | // This include is mandatory for all shaders since the [LayerBuffer] always
2 | // set the uniforms defined here
3 | #version 460 core
4 | #include
5 | precision mediump float;
6 |
7 |
8 | // add `uniform sampler2D iChannel[0-N];` into frag source as needed
9 | uniform vec2 iResolution;
10 | uniform float iTime;
11 | uniform float iFrame;
12 | uniform vec4 iMouse;
13 |
14 | out vec4 fragColor;
--------------------------------------------------------------------------------
/example/assets/shaders/common/main_shadertoy.frag:
--------------------------------------------------------------------------------
1 | void main() {
2 | // Shader compiler optimizations will remove unusued uniforms.
3 | // Since [LayerBuffer.computeLayer] needs to always set these uniforms, when
4 | // this happens, an error occurs when calling setFloat()
5 | // `IndexError (RangeError (index): Index out of range: index should be less than 3: 3)`
6 | // With the following line, the compiler will not remove unusued
7 | float tmp = (iFrame/iFrame) * (iMouse.x/iMouse.x) *
8 | (iTime/iTime) * (iResolution.x/iResolution.x);
9 | if (tmp != 1.) tmp = 1.;
10 |
11 | mainImage( fragColor, FlutterFragCoord().xy * tmp );
12 | }
--------------------------------------------------------------------------------
/example/assets/shaders/filters/black.frag:
--------------------------------------------------------------------------------
1 | // credits:
2 | // https://github.com/PixiColorEffects/pixi-color-effects/blob/main/src/filters/black/fragment.frag
3 |
4 | // including this is mandatory since the [LayerBuffer] always
5 | // set the uniforms defined in common_header.frag
6 | #include <../common/common_header.frag>
7 |
8 | // this is already defined in the common_header.frag
9 | // precision highp float;
10 |
11 | // I think this is manage by PixiColorEffects internally and
12 | // should represend the normalized windows size.
13 | // Its definition is moved in main()
14 | // varying vec2 vTextureCoord;
15 |
16 | uniform sampler2D uSampler;
17 | uniform float value; // this should be in 0-255 range
18 |
19 | void main() {
20 |
21 | vec2 vTextureCoord = FlutterFragCoord().xy / iResolution.xy;
22 |
23 | float bval = value / 255.0;
24 | float wval = (255.0 / (255.0 - value));
25 |
26 | // texture2D is not a SKSL function. Renaming it to "texture"
27 | // vec3 color = texture2D(uSampler, vTextureCoord).rgb;
28 | vec3 color = texture(uSampler, vTextureCoord).rgb;
29 | color = color * wval - (bval * wval);
30 |
31 | // gl_FragColor is named "fragColor"
32 | // texture2D is not a SKSL function. Renaming to "texture"
33 | // gl_FragColor = vec4(color, texture2D(uSampler, vTextureCoord).a);
34 | fragColor = vec4(color, texture(uSampler, vTextureCoord).a);
35 | }
36 |
--------------------------------------------------------------------------------
/example/assets/shaders/filters/white.frag:
--------------------------------------------------------------------------------
1 | // credits:
2 | // https://github.com/PixiColorEffects/pixi-color-effects/blob/main/src/filters/white/fragment.frag
3 |
4 | // including this is mandatory since the [LayerBuffer] always
5 | // set the uniforms defined in common_header.frag
6 | #include <../common/common_header.frag>
7 |
8 | // this is already defined in the common_header.frag
9 | // precision highp float;
10 |
11 | // I think this is manage by PixiColorEffects internally and
12 | // should represend the normalized windows size.
13 | // Its definition is moved in main()
14 | // varying vec2 vTextureCoord;
15 |
16 | uniform sampler2D uSampler;
17 | uniform float value; // this should be in 0-255 range
18 |
19 | void main() {
20 |
21 | vec2 vTextureCoord = FlutterFragCoord().xy / iResolution.xy;
22 |
23 | float bval = 0.0 / 255.0;
24 | float wval = (255.0 / (value - 255.0) * -1.0);
25 |
26 | // texture2D is not a SKSL function. Renaming it to "texture"
27 | // vec3 color = texture2D(uSampler, vTextureCoord).rgb;
28 | vec3 color = texture(uSampler, vTextureCoord).rgb;
29 | color = color * wval - (bval * wval);
30 |
31 | // gl_FragColor is named "fragColor"
32 | // texture2D is not a SKSL function. Renaming to "texture"
33 | // gl_FragColor = vec4(color, texture2D(uSampler, vTextureCoord).a);
34 | fragColor = vec4(color, texture(uSampler, vTextureCoord).a);
35 | }
--------------------------------------------------------------------------------
/example/assets/shaders/mouse1.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
4 | // credits:
5 | // https://www.shadertoy.com/view/XlyBzt
6 |
7 | // ------ START SHADERTOY CODE -----
8 | void mainImage( out vec4 fragColor, in vec2 fragCoord )
9 | {
10 | vec3 col = vec3(0.);
11 |
12 | //Draw a red cross where the mouse button was last down.
13 | if(abs(iMouse.x-fragCoord.x) < 4.) {
14 | col = vec3(1.,0.,0.);
15 | }
16 | if(abs(iMouse.y-fragCoord.y) < 4.) {
17 | col = vec3(1.,0.,0.);
18 | }
19 |
20 | //If the button is currently up, (iMouse.z, iMouse.w) is where the mouse
21 | //was when the button last went down.
22 | if(abs(iMouse.z-fragCoord.x) < 2.) {
23 | col = vec3(0.,0.,1.);
24 | }
25 | if(abs(iMouse.w-fragCoord.y) < 2.) {
26 | col = vec3(0.,0.,1.);
27 | }
28 |
29 | //If the button is currently down, (-iMouse.z, -iMouse.w) is where
30 | //the button was when the click occurred.
31 | if(abs(-iMouse.z-fragCoord.x) < 2.) {
32 | col = vec3(0.,1.,0.);
33 | }
34 | if(abs(-iMouse.w-fragCoord.y) < 2.) {
35 | col = vec3(0.,1.,0.);
36 | }
37 |
38 | fragColor = vec4(col, 1.0);
39 | }
40 | // ------ END SHADERTOY CODE -----
41 |
42 |
43 |
44 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/mouse2.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
4 |
5 | // credits:
6 | // https://www.shadertoy.com/view/Mss3zH
7 |
8 | // ------ START SHADERTOY CODE -----
9 | float distanceToSegment( vec2 a, vec2 b, vec2 p )
10 | {
11 | vec2 pa = p - a, ba = b - a;
12 | float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
13 | return length( pa - ba*h );
14 | }
15 |
16 | void mainImage( out vec4 fragColor, in vec2 fragCoord )
17 | {
18 | vec2 p = fragCoord / iResolution.x;
19 | vec2 cen = 0.5*iResolution.xy/iResolution.x;
20 | vec4 m = iMouse / iResolution.x;
21 |
22 | vec3 col = vec3(0.0);
23 |
24 | if( m.z>0.0 ) // button is down
25 | {
26 | float d = distanceToSegment( m.xy, abs(m.zw), p );
27 | col = mix( col, vec3(1.0,1.0,0.0), 1.0-smoothstep(.004,0.008, d) );
28 | }
29 | if( m.w>0.0 ) // button click
30 | {
31 | col = mix( col, vec3(1.0,1.0,1.0), 1.0-smoothstep(0.1,0.105, length(p-cen)) );
32 | }
33 |
34 | col = mix( col, vec3(1.0,0.0,0.0), 1.0-smoothstep(0.03,0.035, length(p- m.xy )) );
35 | col = mix( col, vec3(0.0,0.0,1.0), 1.0-smoothstep(0.03,0.035, length(p-abs(m.zw))) );
36 |
37 | fragColor = vec4( col, 1.0 );
38 | }
39 | // ------ END SHADERTOY CODE -----
40 |
41 |
42 |
43 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/noise_fade.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | uniform sampler2D iChannel0;
4 | uniform sampler2D iChannel1;
5 |
6 |
7 | // credits:
8 | // https://www.shadertoy.com/view/MstBzf
9 |
10 | // ------ START SHADERTOY CODE -----
11 | float seed = 16.0;
12 | float sinNoise(vec2 uv)
13 | {
14 | return fract(abs(sin(uv.x * 180.0 + uv.y * 3077.0) * 53703.27));
15 | }
16 |
17 | float valueNoise(vec2 uv, float scale)
18 | {
19 | vec2 luv = fract(uv * scale);
20 | vec2 luvs = smoothstep(0.0, 1.0, fract(uv * scale));
21 | vec2 id = floor(uv * scale);
22 | float tl = sinNoise(id + vec2(0.0, 1.0));
23 | float tr = sinNoise(id + vec2(1.0, 1.0));
24 | float t = mix(tl, tr, luvs.x);
25 |
26 | float bl = sinNoise(id + vec2(0.0, 0.0));
27 | float br = sinNoise(id + vec2(1.0, 0.0));
28 | float b = mix(bl, br, luvs.x);
29 |
30 | return mix(b, t, luvs.y) * 2.0 - 1.0;
31 | }
32 |
33 | void mainImage( out vec4 fragColor, in vec2 fragCoord )
34 | {
35 | // Normalized pixel coordinates (from 0 to 1)
36 | vec2 uv = fragCoord/iResolution.xy;
37 |
38 | // uv.y /= iResolution.x/iResolution.y;
39 |
40 | float sinN = sinNoise(uv);
41 |
42 | float scale = 4.0;
43 |
44 | float fractValue = 0.0;
45 | float amp = 1.0;
46 | for(int i = 0; i < 16; i++)
47 | {
48 | fractValue += valueNoise(uv, float(i + 1) * scale) * amp;
49 | amp /= 2.0;
50 | }
51 |
52 | fractValue /= 2.0;
53 | fractValue += 0.5;
54 |
55 | float time = mix(-0.5, 1.0, cos(iTime)/2.0 +0.5);
56 | //time = 1.0;
57 | float cutoff = smoothstep(time+ 0.1, time- 0.1, fractValue);
58 |
59 | vec4 col = mix(texture(iChannel1, uv), texture(iChannel0, uv), cutoff);
60 |
61 | // Output to screen
62 | fragColor = vec4(col);
63 | }
64 | // ------ END SHADERTOY CODE -----
65 |
66 |
67 |
68 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/page_curl.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | uniform sampler2D iChannel0;
4 | uniform sampler2D iChannel1;
5 |
6 | // credits:
7 | // https://www.shadertoy.com/view/ls3cDB
8 |
9 | // ------ START SHADERTOY CODE -----
10 | #define pi 3.14159265359
11 | #define radius .1
12 |
13 | void mainImage( out vec4 fragColor, in vec2 fragCoord )
14 | {
15 | float aspect = iResolution.x / iResolution.y;
16 |
17 | vec2 uv = fragCoord * vec2(aspect, 1.) / iResolution.xy;
18 | vec2 mouse = iMouse.xy * vec2(aspect, 1.) / iResolution.xy;
19 | // mouse.y = 0.; // fix movements horizontally
20 | vec2 mouseDir = normalize(abs(iMouse.zw) - iMouse.xy);
21 | // mouseDir.y = 0.; // fix movements horizontally
22 | vec2 origin = clamp(mouse - mouseDir * mouse.x / mouseDir.x, 0., 1.);
23 | // origin.y = 0.; // fix movements horizontally
24 |
25 | float mouseDist = clamp(length(mouse - origin)
26 | + (aspect - (abs(iMouse.z) / iResolution.x) * aspect) / mouseDir.x, 0., aspect / mouseDir.x);
27 |
28 | if (mouseDir.x < 0.)
29 | {
30 | mouseDist = distance(mouse, origin);
31 | }
32 |
33 | float proj = dot(uv - origin, mouseDir);
34 | float dist = proj - mouseDist;
35 |
36 | vec2 linePoint = uv - dist * mouseDir;
37 |
38 | if (dist > radius)
39 | {
40 | fragColor = texture(iChannel1, uv * vec2(1. / aspect, 1.));
41 | fragColor.rgb *= pow(clamp(dist - radius, 0., 1.) * 1.5, .2);
42 | }
43 | else if (dist >= 0.)
44 | {
45 | // map to cylinder point
46 | float theta = asin(dist / radius);
47 | vec2 p2 = linePoint + mouseDir * (pi - theta) * radius;
48 | vec2 p1 = linePoint + mouseDir * theta * radius;
49 | uv = (p2.x <= aspect && p2.y <= 1. && p2.x > 0. && p2.y > 0.) ? p2 : p1;
50 | fragColor = texture(iChannel0, uv * vec2(1. / aspect, 1.));
51 | fragColor.rgb *= pow(clamp((radius - dist) / radius, 0., 1.), .2);
52 | }
53 | else
54 | {
55 | vec2 p = linePoint + mouseDir * (abs(dist) + pi * radius);
56 | uv = (p.x <= aspect && p.y <= 1. && p.x > 0. && p.y > 0.) ? p : uv;
57 | fragColor = texture(iChannel0, uv * vec2(1. / aspect, 1.));
58 | }
59 | }
60 | // ------ END SHADERTOY CODE -----
61 |
62 |
63 |
64 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/ripple.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | uniform sampler2D iChannel0;
4 |
5 | // credits:
6 | // https://www.shadertoy.com/view/4djGzz
7 |
8 | // ------ START SHADERTOY CODE -----
9 | // MTAT.03.015 Computer Graphics
10 | // https://courses.cs.ut.ee/2013/cg/
11 | //
12 | // Basic ripple effect example
13 |
14 |
15 | // Params = (wave frequency in Hz, number of waves per unit distance)
16 | //
17 | vec2 params = vec2(2.5, 10.0);
18 |
19 | // Simple circular wave function
20 | float wave(vec2 pos, float t, float freq, float numWaves, vec2 center) {
21 | float d = length(pos - center);
22 | d = log(1.0 + exp(d));
23 | return 1.0/(1.0+20.0*d*d) *
24 | sin(2.0*3.1415*(-numWaves*d + t*freq));
25 | }
26 |
27 | // This height map combines a couple of waves
28 | float height(vec2 pos, float t) {
29 | float w;
30 | w = wave(pos, t, params.x, params.y, vec2(0.5, -0.5));
31 | w += wave(pos, t, params.x, params.y, -vec2(0.5, -0.5));
32 | return w;
33 | }
34 |
35 | // Discrete differentiation
36 | vec2 normal(vec2 pos, float t) {
37 | return vec2(height(pos - vec2(0.01, 0), t) - height(pos, t),
38 | height(pos - vec2(0, 0.01), t) - height(pos, t));
39 | }
40 |
41 | // Simple ripple effect
42 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
43 | if (iMouse.z > 0.0) params = 2.0*params*iMouse.xy/iResolution.xy;
44 | else params = vec2(2.5, 10.0);
45 |
46 | vec2 uv = fragCoord.xy / iResolution.xy;
47 | vec2 uvn = 2.0*uv - vec2(1.0);
48 | uv += normal(uvn, iTime);
49 | fragColor = texture(iChannel0, vec2(1.0-uv.x, uv.y));
50 | }
51 | // ------ END SHADERTOY CODE -----
52 |
53 |
54 |
55 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/shader1_bufferA.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | uniform sampler2D iChannel0;
4 |
5 |
6 |
7 | // ------ START SHADERTOY CODE -----
8 | // basic feedback mechanism by Xavierseb
9 | void mainImage( out vec4 fragColor, in vec2 fragCoord ){
10 |
11 | vec2 mouse = iMouse.xy;
12 | // if mouse not detected do something
13 | if(mouse.x <= 0.) mouse = vec2( iResolution.x * (sin(iTime)+1.)/2., iResolution.y/2.);
14 |
15 | // diameter of blob and intensity in same formula because why not
16 | vec3 blob = vec3(.10-clamp(length((fragCoord.xy-mouse.xy)/iResolution.x),0.,.11));
17 |
18 | vec3 stack= texture(iChannel0,fragCoord.xy/iResolution.xy).xyz * vec3(0.99,.982,.93);
19 |
20 | fragColor = vec4(stack + blob, 1.0);
21 | }
22 | // ------ END SHADERTOY CODE -----
23 |
24 |
25 |
26 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/shader1_main.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | uniform sampler2D iChannel0;
4 |
5 |
6 |
7 | // credits:
8 | // https://www.shadertoy.com/view/WlsGRM
9 |
10 | // ------ START SHADERTOY CODE -----
11 | void mainImage( out vec4 fragColor, in vec2 fragCoord ){
12 | fragColor = vec4(texture(iChannel0,fragCoord.xy/iResolution.xy).xyz,1.0);
13 | }
14 | // ------ END SHADERTOY CODE -----
15 |
16 |
17 |
18 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/shader2_bufferA.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | uniform sampler2D iChannel0;
4 |
5 |
6 |
7 |
8 | // ------ START SHADERTOY CODE -----
9 | #define PAINT_MODE 4
10 | #define MIX_MODE 1
11 |
12 | const float mixPercent = 0.1;
13 | const float brushRadius = 10.0;
14 |
15 | // IMPORTANT: mixPair must be symmetric: mixPair(a,b) + mixPair(b,a) == 0
16 | #if MIX_MODE == 1
17 | vec2 mixPair(vec2 a, vec2 b)
18 | {
19 | return (b - a) * mixPercent;
20 | }
21 | #elif MIX_MODE == 2
22 | vec2 mixPair(vec2 a, vec2 b)
23 | {
24 | vec2 sum = vec2(a.x + a.y, b.x + b.y);
25 | float amount = (sum.y - sum.x);
26 | float totalBig = max(sum.x, sum.y);
27 | if (totalBig == 0.0)
28 | return vec2(0.0, 0.0);
29 |
30 | vec2 movement;
31 | if (amount < 0.0)
32 | {
33 | movement = amount * a / totalBig;
34 | }
35 | else
36 | {
37 | movement = amount * b / totalBig;
38 | }
39 |
40 | return movement * mixPercent;
41 | }
42 | #endif
43 |
44 | vec2 mixNeighbors(vec2 uv, vec4 center)
45 | {
46 | // vec2 tx1 = 1.0 / iResolution.xy;
47 | vec2 tx1 = vec2(2.0, 2.0);
48 | vec4 nx0 = texture(iChannel0, uv + vec2(-tx1.x, 0));
49 | vec4 nx1 = texture(iChannel0, uv + vec2(tx1.x, 0));
50 | vec4 ny0 = texture(iChannel0, uv + vec2(0, -tx1.y));
51 | vec4 ny1 = texture(iChannel0, uv + vec2(0, tx1.y));
52 |
53 | vec2 result = center.yw;
54 | result += mixPair(center.yw, nx0.yw);
55 | result += mixPair(center.yw, nx1.yw);
56 | result += mixPair(center.yw, ny0.yw);
57 | result += mixPair(center.yw, ny1.yw);
58 | return result;
59 | }
60 |
61 | void mainImage(out vec4 fragColor, in vec2 fragCoord)
62 | {
63 | vec2 uv = fragCoord.xy / iResolution.xy;
64 | vec4 prev = texture(iChannel0, uv);
65 |
66 | prev.yw = mixNeighbors(uv, prev);
67 |
68 | float brush = 0.0;
69 | if (iMouse.z >= 0.0)
70 | {
71 | float d = distance(iMouse.xy, fragCoord.xy);
72 | d /= brushRadius * 3.0;
73 | brush = clamp(1.0 - d * d * d * d, -0.0, 1.0);
74 | }
75 |
76 | vec2 mmask = vec2(1.4, 0.02);
77 |
78 | #if PAINT_MODE == 1
79 | vec2 amt = prev.yw + mmask * brush;
80 | #elif PAINT_MODE == 2
81 | vec2 amt = mix(prev.yw, mmask, brush);
82 | #elif PAINT_MODE == 3
83 | vec2 amt = mix(prev.yw, prev.yw * mmask, brush) + mmask * brush;
84 | #elif PAINT_MODE == 4
85 | float prevTotal = prev.y + prev.w;
86 | vec2 newVal = (vec2(prevTotal, prevTotal) + brush) * mmask;
87 | vec2 amt = mix(prev.yw, newVal, brush);
88 | #endif
89 |
90 | fragColor = vec4(0.0, amt.x, 1.0, amt.y/2.);
91 | }
92 | // ------ END SHADERTOY CODE -----
93 |
94 |
95 |
96 |
97 |
98 |
99 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/shader2_main.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | uniform sampler2D iChannel0;
4 |
5 |
6 | // https://www.shadertoy.com/view/4lySDc
7 |
8 |
9 |
10 | // ------ START SHADERTOY CODE -----
11 | vec2 lighting(vec2 uv)
12 | {
13 | // vec2 tx1 = 1.0 / iResolution.xy;
14 | vec2 tx1 = vec2(3.0, 3.0);
15 | vec4 nx0 = texture(iChannel0, uv + vec2(-tx1.x, 0));
16 | vec4 nx1 = texture(iChannel0, uv + vec2(tx1.x, 0));
17 | vec4 ny0 = texture(iChannel0, uv + vec2(0, -tx1.y));
18 | vec4 ny1 = texture(iChannel0, uv + vec2(0, tx1.y));
19 |
20 | float ax0 = nx0.y + nx0.w;
21 | float ax1 = nx1.y + nx1.w;
22 | float ay0 = ny0.y + ny0.w;
23 | float ay1 = ny1.y + ny1.w;
24 |
25 | vec3 tx = vec3(0.35, 0.0, ax0 - ax1);
26 | vec3 ty = vec3(0.0, 0.35, ay0 - ay1);
27 | vec3 N = normalize(cross(tx, ty));
28 |
29 | vec3 L = normalize(vec3(1.0, 1.0, 2.0));
30 |
31 | float diff = max(dot(N, L) * 0.65 + 0.35, 0.0);
32 | float spec = clamp(dot(reflect(L, N),vec3(0., 0., -1.)), 0.0, 1.0);
33 | spec = pow(spec, 12.0);
34 |
35 | return vec2(diff, spec);
36 | }
37 |
38 | void mainImage( out vec4 fragColor, in vec2 fragCoord )
39 | {
40 | vec2 uv = fragCoord.xy / iResolution.xy;
41 | vec4 mat = texture(iChannel0, uv);
42 |
43 | vec3 color0 = vec3(1.0, 1.0, 0.0);
44 | vec3 color1 = vec3(0.0, 0.0, 0.0);
45 |
46 | // normalize material density
47 | float matTotal = mat.y + mat.w;
48 | if (matTotal > 1.0)
49 | mat.yw /= matTotal;
50 |
51 | vec3 matColor = color0 * mat.y + color1 * mat.w;
52 | vec2 light = lighting(uv);
53 | vec3 finalColor = matColor * light.x + light.y;
54 |
55 | fragColor = vec4(finalColor, 1.0);
56 | }
57 | // ------ END SHADERTOY CODE -----
58 |
59 |
60 |
61 |
62 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/test.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
4 |
5 | // credits:
6 | // https://www.shadertoy.com/view/MttGz7
7 | // https://inspirnathan.com/posts/53-shadertoy-tutorial-part-7/ @method #3
8 |
9 | // ------ START SHADERTOY CODE -----
10 | // Fork of "zpm test raymarching" by zpm. https://shadertoy.com/view/MclSzX
11 | // 2024-01-20 08:41:14
12 |
13 | // https://inspirnathan.com/posts/53-shadertoy-tutorial-part-7/ @method #3
14 |
15 | #define MAX_MARCHING_STEPS 85.
16 | #define MIN_DIST 0.0
17 | #define MAX_DIST 60.0
18 | #define PRECISION 0.0001
19 | #define EPSILON 0.0001
20 | #define DISTANCE_BIAS 0.7
21 | #define PI 3.14159265359
22 |
23 | #define COLOR_BACKGROUND vec3(0., 0., 0.)
24 | #define COLOR_AMBIENT vec3(0.1, 0.1, 0.1)
25 |
26 | #define MAT_RED vec3(1.,0.,0.)
27 | #define MAT_1 vec3(0.443,0.725,0.953)
28 | #define MAT_2 vec3(0.353,0.671,0.980)
29 | #define MAT_3 vec3(0.208,0.278,0.627)
30 | #define MAT_4 vec3(1. + 0.7*mod(floor(p.x) + floor(p.z), 2.0))
31 |
32 |
33 | float dot2( in vec3 v ) { return dot(v,v); }
34 |
35 |
36 |
37 | float sdPlane(vec3 p)
38 | {
39 | return p.y;
40 | }
41 |
42 | float sdSphere(vec3 p, float r, vec3 offset)
43 | {
44 | return length(p - offset) - r;
45 | }
46 |
47 | // Distance from p to box whose half-dimensions are b.x, b.y, b.z
48 | float sdBox( vec3 p, vec3 b )
49 | {
50 | vec3 d = abs(p) - b;
51 | return min( max(d.x,max(d.y,d.z) ),0.0) + length(max(d,0.0));
52 | }
53 |
54 | // Distance from p to box of half-dimensions b.x,y,z plus buffer radius r
55 | float udRoundBox( vec3 p, vec3 b, float r)
56 | {
57 | return length( max(abs(p)-b,0.0) )-r;
58 | }
59 |
60 | float udTriangle( in vec3 v1, in vec3 v2, in vec3 v3, in vec3 p )
61 | {
62 | vec3 v21 = v2 - v1; vec3 p1 = p - v1;
63 | vec3 v32 = v3 - v2; vec3 p2 = p - v2;
64 | vec3 v13 = v1 - v3; vec3 p3 = p - v3;
65 | vec3 nor = cross( v21, v13 );
66 |
67 | return sqrt( (sign(dot(cross(v21,nor),p1)) +
68 | sign(dot(cross(v32,nor),p2)) +
69 | sign(dot(cross(v13,nor),p3))<2.0)
70 | ?
71 | min( min(
72 | dot2(v21*clamp(dot(v21,p1)/dot2(v21),0.0,1.0)-p1),
73 | dot2(v32*clamp(dot(v32,p2)/dot2(v32),0.0,1.0)-p2) ),
74 | dot2(v13*clamp(dot(v13,p3)/dot2(v13),0.0,1.0)-p3) )
75 | :
76 | dot(nor,p1)*dot(nor,p1)/dot2(nor) );
77 | }
78 |
79 |
80 | ///////////////////////
81 | // Matrix
82 | ///////////////////////
83 | mat2 rotate2d(float theta) {
84 | float s = sin(theta), c = cos(theta);
85 | return mat2(c, -s, s, c);
86 | }
87 |
88 | // Rotation matrix around the X axis.
89 | mat3 rotateX(float theta) {
90 | float c = cos(theta);
91 | float s = sin(theta);
92 | return mat3(
93 | vec3(1, 0, 0),
94 | vec3(0, c, -s),
95 | vec3(0, s, c)
96 | );
97 | }
98 |
99 | // Rotation matrix around the Y axis.
100 | mat3 rotateY(float theta) {
101 | float c = cos(theta);
102 | float s = sin(theta);
103 | return mat3(
104 | vec3(c, 0, s),
105 | vec3(0, 1, 0),
106 | vec3(-s, 0, c)
107 | );
108 | }
109 |
110 | // Rotation matrix around the Z axis.
111 | mat3 rotateZ(float theta) {
112 | float c = cos(theta);
113 | float s = sin(theta);
114 | return mat3(
115 | vec3(c, -s, 0),
116 | vec3(s, c, 0),
117 | vec3(0, 0, 1)
118 | );
119 | }
120 |
121 | // Identity matrix.
122 | mat3 identity() {
123 | return mat3(
124 | vec3(1, 0, 0),
125 | vec3(0, 1, 0),
126 | vec3(0, 0, 1)
127 | );
128 | }
129 |
130 |
131 | // This function comes from glsl-rotate https://github.com/dmnsgn/glsl-rotate/blob/main/rotation-3d.glsl
132 | mat4 rotation3d(vec3 axis, float angle) {
133 | axis = normalize(axis);
134 | float s = sin(angle);
135 | float c = cos(angle);
136 | float oc = 1.0 - c;
137 |
138 | return mat4(
139 | oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,
140 | oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,
141 | oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,
142 | 0.0, 0.0, 0.0, 1.0
143 | );
144 | }
145 | vec3 rotate(vec3 v, vec3 axis, float angle) {
146 | mat4 m = rotation3d(axis, angle);
147 | return (m * vec4(v, 1.0)).xyz;
148 | }
149 |
150 |
151 |
152 | ///////////////////////
153 | // Boolean Operators
154 | ///////////////////////
155 | vec4 opUnion(vec4 d1, vec4 d2) {
156 | return (d1.x < d2.x) ? d1 : d2;
157 | }
158 |
159 | float opSmoothUnion(float d1, float d2, float k) {
160 | float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0., 1. );
161 | return mix( d2, d1, h ) - k*h*(1.-h);
162 | }
163 |
164 | vec4 opSmoothUnion(vec4 d1, vec4 d2, float k )
165 | {
166 | float h = clamp(0.5 + 0.5*(d1.x-d2.x)/k, 0., 1.);
167 | vec3 c = mix(d1.yzw, d2.yzw,h);
168 | float d = mix(d1.x, d2.x, h) - k*h*(1.-h);
169 |
170 | return vec4(d, c);
171 | }
172 |
173 |
174 |
175 | vec4 opIntersection(vec4 d1, vec4 d2) {
176 | return (d1.x > d2.x) ? d1 : d2;
177 | }
178 |
179 | float opSmoothIntersection(float d1, float d2, float k) {
180 | float h = clamp( 0.5 - 0.5*(d2-d1)/k, 0.0, 1.0 );
181 | return mix( d2, d1, h ) + k*h*(1.0-h);
182 | }
183 |
184 | vec4 opSmoothIntersection(vec4 d1, vec4 d2, float k )
185 | {
186 | float h = clamp(0.5 - 0.5*(d1.x-d2.x)/k, 0., 1.);
187 | vec3 c = mix(d1.yzw, d2.yzw, h);
188 | float d = mix(d1.x, d2.x, h) + k*h*(1.-h);
189 |
190 | return vec4(d, c);
191 | }
192 |
193 |
194 |
195 | vec4 opSubtraction(vec4 d1, vec4 d2) {
196 | return d1.x > -d2.x ? d1 : vec4(-d2.x, d2.yzw);
197 | }
198 |
199 | float opSmoothSubtraction(float d1, float d2, float k) {
200 | float h = clamp( 0.5 - 0.5*(d2+d1)/k, 0.0, 1.0 );
201 | return mix( d2, -d1, h ) + k*h*(1.0-h);
202 | }
203 |
204 | vec4 opSmoothSubtraction(vec4 d1, vec4 d2, float k)
205 | {
206 | float h = clamp(0.5 - 0.5*(d1.x+d2.x)/k, 0., 1.);
207 | vec3 c = mix(d1.yzw, d2.yzw, h);
208 | float d = mix(d1.x, -d2.x, h ) + k*h*(1.-h);
209 |
210 | return vec4(d, c);
211 | }
212 |
213 |
214 |
215 | float opExtrusion(in vec3 p, in float sdf, in float h) {
216 | vec2 w = vec2(sdf, abs(p.z) - h);
217 | return min(max(w.x, w.y), 0.0) + length(max(w, 0.0));
218 | }
219 |
220 |
221 |
222 | vec4 sdFlutterLogoUncut(vec3 p) {
223 |
224 | p = rotate(p, vec3(0.0, 0.0, 1.0), -PI/4.);
225 |
226 | vec4 roundedBox1 = vec4(
227 | udRoundBox(p+vec3(1.8, -2., 0.), vec3(.3, 1.5, 0.3), 0.05),
228 | MAT_1);
229 | vec4 roundedBox2 = vec4(
230 | udRoundBox(p+vec3(0.71, -1.52, 0.), vec3(.3, 1., 0.3), 0.05),
231 | MAT_1);
232 | vec4 roundedBox3 = vec4(
233 | udRoundBox(p+vec3(0.01, -0.8, 0.01), vec3(1., .3, 0.33), 0.05),
234 | MAT_3);
235 |
236 | vec4 res = opUnion(roundedBox1, roundedBox2);
237 | res = opUnion(res, roundedBox3);
238 | return res;
239 | }
240 |
241 |
242 | vec4 sdFlutterLogo(vec3 p) {
243 | p = rotate(p, vec3(0., 1., 0.), iTime/10.) + vec3(1., sin(iTime)+.5, 0.);
244 |
245 | vec3 s = vec3(8., 0., 5.);
246 | vec3 id = round(p/s);
247 | p = p - s*id;
248 |
249 | vec4 box1 = vec4(
250 | sdBox(p+vec3(-1.1, -3.8, 0.), vec3(.6, .3, 0.5)),
251 | MAT_1);
252 | vec4 box2 = vec4(
253 | sdBox(p+vec3(-1.12, -2.28, 0.), vec3(.6, .25, 0.5)),
254 | MAT_1);
255 | vec4 box3 = vec4(
256 | sdBox(p+vec3(-1.1, .2, 0.), vec3(.6, .25, 0.5)),
257 | MAT_3);
258 | vec4 flutterUncut = sdFlutterLogoUncut(p);
259 |
260 | vec4 res = opUnion(box1, box2);
261 | res = opUnion(res, box3);
262 | res = opSmoothSubtraction(flutterUncut, res, 0.1);
263 | return res;
264 | }
265 |
266 | vec4 scene(vec3 p) {
267 |
268 | vec4 center = vec4(sdSphere(p, .2, vec3(0., 0., 0.)), MAT_RED);
269 | vec4 plane = vec4(sdPlane(p), MAT_4);
270 |
271 | vec3 p1 = rotate(p, vec3(0., 1., 0.), iTime/4.) +
272 | vec3(1., sin(iTime)*2.+1.3 , 0.);
273 | vec4 flutterLogo = sdFlutterLogo(p);
274 |
275 | vec4 res = opUnion(center, plane);
276 | res = opSmoothUnion(res, flutterLogo, 0.3);
277 | return res;
278 | }
279 |
280 | vec4 rayMarch(vec3 ro, vec3 rd) {
281 | float depth = MIN_DIST;
282 | vec4 d; // .yzw color .x distance ray has travelled
283 |
284 | for (float i = 0.; i < MAX_MARCHING_STEPS; i++) {
285 | vec3 p = ro + depth * rd;
286 | d = scene(p);
287 | depth += d.x * DISTANCE_BIAS;
288 | if (d.x < PRECISION || depth > MAX_DIST) break;
289 | }
290 |
291 | d.x = depth;
292 |
293 | return d;
294 | }
295 |
296 | vec3 calcNormal(in vec3 p) {
297 | vec2 e = vec2(1, -1) * EPSILON;
298 | return normalize(
299 | e.xyy * scene(p + e.xyy).x +
300 | e.yyx * scene(p + e.yyx).x +
301 | e.yxy * scene(p + e.yxy).x +
302 | e.xxx * scene(p + e.xxx).x);
303 | }
304 |
305 | mat3 camera(vec3 cameraPos, vec3 lookAtPoint) {
306 | vec3 cd = normalize(lookAtPoint - cameraPos);
307 | vec3 cr = normalize(cross(vec3(0, 1, 0), cd));
308 | vec3 cu = normalize(cross(cd, cr));
309 |
310 | return mat3(-cr, cu, -cd);
311 | }
312 |
313 | void mainImage( out vec4 fragColor, in vec2 fragCoord )
314 | {
315 | vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y;
316 | vec2 mouseUV = iMouse.xy/iResolution.xy;
317 | uv = vec2(uv.x, 1. - uv.y);
318 | mouseUV = vec2(mouseUV.x, 1. - mouseUV.y);
319 |
320 | if (iMouse.xy == vec2(1.0))
321 | mouseUV = vec2(0.6, 0.3); // trick to center mouse on page load
322 |
323 | vec3 col = vec3(0.);
324 | vec3 lp = vec3(0., -16., 0.);
325 | vec3 ro = vec3(-15., 3., 2.); // ray origin that represents camera position
326 |
327 | float cameraRadius = 2.;
328 | ro.yz = ro.yz * cameraRadius * rotate2d(mix(-PI/2., PI/2., mouseUV.y));
329 | ro.xz = ro.xz * rotate2d(mix(-PI, PI, mouseUV.x)) + vec2(lp.x, lp.z);
330 |
331 | vec3 rd = camera(ro, lp) * normalize(vec3(uv, -1.)); // ray direction
332 |
333 | vec4 d = rayMarch(ro, rd); // .yzw color .x signed distance value to closest object
334 |
335 | if (d.x > MAX_DIST) {
336 | col = COLOR_BACKGROUND; // ray didn't hit anything
337 | } else {
338 | vec3 p = ro + rd * d.x; // point discovered from ray marching
339 | vec3 normal = calcNormal(p); // surface normal
340 |
341 | vec3 lightPosition = vec3(0., 5., 2.);
342 | vec3 lightDirection = normalize(lightPosition - p) * .65; // The 0.65 is used to decrease the light intensity a bit
343 |
344 | float dif = clamp(dot(normal, lightDirection), 0., 1.) * 0.5 + 0.5; // diffuse reflection mapped to values between 0.5 and 1.0
345 |
346 | col = dif * d.yzw + COLOR_AMBIENT;
347 |
348 | }
349 |
350 | fragColor = vec4(col, 1.0);
351 | }
352 | // ------ END SHADERTOY CODE -----
353 |
354 |
355 |
356 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/test_isself_buffer_a.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
4 | uniform float R;
5 | uniform float G;
6 | uniform float B;
7 |
8 | void mainImage( out vec4 fragColor, in vec2 fragCoord )
9 | {
10 | vec2 uv = fragCoord/iResolution.xy;
11 | vec4 col;
12 | float radius = 50.;
13 |
14 | float dist = clamp(0., 60., 60. / distance(iMouse.xy, fragCoord));
15 | col = vec4(0., 0., 0., 0.);
16 | if (dist < radius)
17 | col = vec4(R * dist, G * dist, B * dist, 1.);
18 |
19 | // vec2 from = uv-vec2(sin(iTime) * 0.1, cos(iTime) * 0.1);
20 | // vec4 col2 = texture(iChannel0, from) * 0.8;
21 |
22 | // fragColor = col + col2;
23 | fragColor = col;
24 | }
25 |
26 |
27 |
28 | #include
29 |
30 |
--------------------------------------------------------------------------------
/example/assets/shaders/test_isself_main.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | uniform sampler2D iChannel0;
4 |
5 |
6 |
7 | // ------ START SHADERTOY CODE -----
8 | void mainImage( out vec4 fragColor, in vec2 fragCoord )
9 | {
10 | // Normalized pixel coordinates (from 0 to 1)
11 | vec2 uv = fragCoord/iResolution.xy;
12 |
13 | // Time varying pixel color
14 | vec4 col = texture(iChannel0, uv);
15 | fragColor = col;
16 | }
17 | // ------ END SHADERTOY CODE -----
18 |
19 |
20 |
21 | #include
--------------------------------------------------------------------------------
/example/assets/shaders/water.frag:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | uniform sampler2D iChannel0;
4 |
5 |
6 |
7 | // credits:
8 | // https://www.shadertoy.com/view/Mls3DH
9 |
10 | // ------ START SHADERTOY CODE -----
11 | uniform float speed; // 0.6
12 | uniform float frequency; // 8.0
13 | uniform float amplitude; // 1.0
14 |
15 |
16 | // [2TC 15] Water2D
17 | // Copyleft {c} 2015 Michael Pohoreski
18 | // Chars: 260
19 | //
20 | // Notes:
21 | // - If you want to speed up / slow this down, change the contant in `d` iTime*0.2
22 | //
23 | // - A "naive" water filter is:
24 | // #define F cos(x)*cos(y),sin(x)*sin(y)
25 | // We use this one:
26 | // #define F cos(x-y)*cos(y),sin(x+y)*sin(y)
27 | // Feel free to post your suggestions!
28 | //
29 | // For uber minification,
30 | // - You can replace:
31 | // 2.0 / uvResolution.x
32 | // With say a hard-coded constant:
33 | // 0.007
34 | // Inline the #define
35 |
36 | // Minified
37 |
38 | #if 0
39 |
40 | #define F cos(x-y)*cos(y),sin(x+y)*sin(y)
41 | vec2 s(vec2 p){float d=iTime*0.2,x=8.*(p.x+d),y=8.*(p.y+d);return vec2(F);}
42 | void mainImage( out vec4 f, in vec2 w ){vec2 i=iResolution.xy,r=w/i,q=r+2./iResolution.x*(s(r)-s(r+i));q.y=1.-q.y;f=texture(iChannel0,q);}
43 |
44 |
45 | #else
46 | // Cleaned up Source
47 |
48 | vec2 shift( vec2 p ) {
49 | float d = iTime*speed;
50 | vec2 f = frequency * (p + d);
51 | vec2 q = cos( vec2(
52 | cos(f.x-f.y)*cos(f.y),
53 | sin(f.x+f.y)*sin(f.y) ) );
54 | return q;
55 | }
56 |
57 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
58 | vec2 r = fragCoord.xy / iResolution.xy;
59 | vec2 p = shift( r );
60 | vec2 q = shift(r + 1.0);
61 | float amp = amplitude * 60.0 / iResolution.x;
62 | vec2 s = r + amp * (p - q);
63 | s.y = 1. - s.y; // flip Y axis for ShaderToy
64 | fragColor = texture( iChannel0, s );
65 | }
66 | #endif
67 |
68 |
69 |
70 |
71 | void main() {
72 | // Shader compiler optimizations will remove unusued uniforms.
73 | // Since [LayerBuffer.computeLayer] needs to always set these uniforms, when
74 | // this happens, an error occurs when calling setFloat()
75 | // `IndexError (RangeError (index): Index out of range: index should be less than 3: 3)`
76 | // With the following line, the compiler will not remove unusued
77 | float tmp = (iFrame/iFrame) * (iMouse.x/iMouse.x) *
78 | (iTime/iTime) * (iResolution.x/iResolution.x);
79 | if (tmp != 1.) tmp = 1.;
80 |
81 | mainImage( fragColor, FlutterFragCoord().xy * tmp );
82 | }
--------------------------------------------------------------------------------
/example/example.md:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shader_buffers/shader_buffers.dart';
3 |
4 | void main() {
5 | runApp(MainApp());
6 | }
7 |
8 | class MainApp extends StatelessWidget {
9 | MainApp({super.key});
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | final controller = ShaderController();
14 | final mainLayer = LayerBuffer(
15 | shaderAssetsName: 'assets/shaders/mouse2.frag',
16 | );
17 | return MaterialApp(
18 | themeMode: ThemeMode.dark,
19 | darkTheme: ThemeData.dark(useMaterial3: true),
20 | theme: ThemeData(scaffoldBackgroundColor: Colors.black),
21 | home: Scaffold(
22 | body: Padding(
23 | padding: const EdgeInsets.all(16),
24 | child: ShaderBuffers(
25 | controller: controller,
26 | // width: 350,
27 | // height: 200,
28 | mainImage: mainLayer,
29 | startPaused: false,
30 | ),
31 | ),
32 | ),
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
65 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Example
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | example
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | CADisableMinimumFrameDurationOnPhone
45 |
46 | UIApplicationSupportsIndirectInputEvents
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/example/lib/simple_layers.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: avoid_multiple_declarations_per_line, public_member_api_docs
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:shader_buffers/shader_buffers.dart';
5 |
6 | /// Code to demostrate the use of multiple image filter fragment shaders
7 | /// to apply in sequence to a single image. Something like this:
8 | /// https://github.com/alnitak/shader_buffers?tab=readme-ov-file#layering-shaders
9 | ///
10 | /// Please, read the comments of fragment source code
11 | /// located in `assets/shaders/filters` and the documentation
12 | /// for writing a fragment shader
13 | /// https://github.com/alnitak/shader_buffers?tab=readme-ov-file#writing-a-fragment-shader
14 |
15 | void main() {
16 | runApp(const MainApp());
17 | }
18 |
19 | class MainApp extends StatefulWidget {
20 | const MainApp({super.key});
21 |
22 | @override
23 | State createState() => _MainAppState();
24 | }
25 |
26 | class _MainAppState extends State {
27 | /// the shader controller
28 | late ShaderController controller;
29 |
30 | /// the buffers used here
31 | late LayerBuffer mainImage, bufferA;
32 |
33 | /// the control sliders for uniforms
34 | late ValueNotifier valueWhite, valueBlack;
35 |
36 | @override
37 | void initState() {
38 | super.initState();
39 |
40 | controller = ShaderController();
41 | valueWhite = ValueNotifier(0);
42 | valueBlack = ValueNotifier(0);
43 |
44 | /// initialize the mandatory [layerBuffer] and its uniforms
45 | mainImage = LayerBuffer(
46 | shaderAssetsName: 'assets/shaders/filters/black.frag',
47 | uniforms: Uniforms(
48 | [
49 | Uniform(
50 | value: 0,
51 | name: 'value',
52 | range: const RangeValues(0, 255),
53 | defaultValue: 0,
54 | ),
55 | ],
56 | ),
57 | );
58 |
59 | /// initialize the second buffer and its uniforms
60 | bufferA = LayerBuffer(
61 | shaderAssetsName: 'assets/shaders/filters/white.frag',
62 | uniforms: Uniforms(
63 | [
64 | Uniform(
65 | value: 0,
66 | name: 'value',
67 | range: const RangeValues(0, 255),
68 | defaultValue: 0,
69 | ),
70 | ],
71 | ),
72 | );
73 |
74 | /// tells the main layer to use the [bufferA] output as a texture uniform
75 | mainImage.setChannels([IChannel(buffer: bufferA)]);
76 |
77 | /// tells the first layer to use an image as a texture uniform
78 | bufferA.setChannels([IChannel(assetsTexturePath: 'assets/flutter.png')]);
79 | }
80 |
81 | @override
82 | Widget build(BuildContext context) {
83 | return MaterialApp(
84 | home: Scaffold(
85 | body: Column(
86 | children: [
87 | ValueListenableBuilder(
88 | valueListenable: valueWhite,
89 | builder: (_, v, __) {
90 | return Slider(
91 | value: v,
92 | max: 255,
93 | onChanged: (sliderValue) {
94 | mainImage.uniforms!.uniforms.first.value = sliderValue;
95 | valueWhite.value = sliderValue;
96 | },
97 | );
98 | },
99 | ),
100 | ValueListenableBuilder(
101 | valueListenable: valueBlack,
102 | builder: (_, v, __) {
103 | return Slider(
104 | value: v,
105 | max: 255,
106 | onChanged: (sliderValue) {
107 | bufferA.uniforms!.uniforms.first.value = sliderValue;
108 | valueBlack.value = sliderValue;
109 | },
110 | );
111 | },
112 | ),
113 | Expanded(
114 | child: ShaderBuffers(
115 | controller: controller,
116 | mainImage: mainImage,
117 | buffers: [bufferA],
118 | ),
119 | ),
120 | ],
121 | ),
122 | ),
123 | );
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/example/linux/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral
2 |
--------------------------------------------------------------------------------
/example/linux/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Project-level configuration.
2 | cmake_minimum_required(VERSION 3.10)
3 | project(runner LANGUAGES CXX)
4 |
5 | # The name of the executable created for the application. Change this to change
6 | # the on-disk name of your application.
7 | set(BINARY_NAME "example")
8 | # The unique GTK application identifier for this application. See:
9 | # https://wiki.gnome.org/HowDoI/ChooseApplicationID
10 | set(APPLICATION_ID "com.example.example")
11 |
12 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
13 | # versions of CMake.
14 | cmake_policy(SET CMP0063 NEW)
15 |
16 | # Load bundled libraries from the lib/ directory relative to the binary.
17 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
18 |
19 | # Root filesystem for cross-building.
20 | if(FLUTTER_TARGET_PLATFORM_SYSROOT)
21 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
22 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
23 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
24 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
25 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
26 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
27 | endif()
28 |
29 | # Define build configuration options.
30 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
31 | set(CMAKE_BUILD_TYPE "Debug" CACHE
32 | STRING "Flutter build mode" FORCE)
33 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
34 | "Debug" "Profile" "Release")
35 | endif()
36 |
37 | # Compilation settings that should be applied to most targets.
38 | #
39 | # Be cautious about adding new options here, as plugins use this function by
40 | # default. In most cases, you should add new options to specific targets instead
41 | # of modifying this function.
42 | function(APPLY_STANDARD_SETTINGS TARGET)
43 | target_compile_features(${TARGET} PUBLIC cxx_std_14)
44 | target_compile_options(${TARGET} PRIVATE -Wall -Werror)
45 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>")
46 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>")
47 | endfunction()
48 |
49 | # Flutter library and tool build rules.
50 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
51 | add_subdirectory(${FLUTTER_MANAGED_DIR})
52 |
53 | # System-level dependencies.
54 | find_package(PkgConfig REQUIRED)
55 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
56 |
57 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
58 |
59 | # Define the application target. To change its name, change BINARY_NAME above,
60 | # not the value here, or `flutter run` will no longer work.
61 | #
62 | # Any new source files that you add to the application should be added here.
63 | add_executable(${BINARY_NAME}
64 | "main.cc"
65 | "my_application.cc"
66 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
67 | )
68 |
69 | # Apply the standard set of build settings. This can be removed for applications
70 | # that need different build settings.
71 | apply_standard_settings(${BINARY_NAME})
72 |
73 | # Add dependency libraries. Add any application-specific dependencies here.
74 | target_link_libraries(${BINARY_NAME} PRIVATE flutter)
75 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
76 |
77 | # Run the Flutter tool portions of the build. This must not be removed.
78 | add_dependencies(${BINARY_NAME} flutter_assemble)
79 |
80 | # Only the install-generated bundle's copy of the executable will launch
81 | # correctly, since the resources must in the right relative locations. To avoid
82 | # people trying to run the unbundled copy, put it in a subdirectory instead of
83 | # the default top-level location.
84 | set_target_properties(${BINARY_NAME}
85 | PROPERTIES
86 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
87 | )
88 |
89 |
90 | # Generated plugin build rules, which manage building the plugins and adding
91 | # them to the application.
92 | include(flutter/generated_plugins.cmake)
93 |
94 |
95 | # === Installation ===
96 | # By default, "installing" just makes a relocatable bundle in the build
97 | # directory.
98 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
99 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
100 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
101 | endif()
102 |
103 | # Start with a clean build bundle directory every time.
104 | install(CODE "
105 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
106 | " COMPONENT Runtime)
107 |
108 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
109 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
110 |
111 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
112 | COMPONENT Runtime)
113 |
114 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
115 | COMPONENT Runtime)
116 |
117 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
118 | COMPONENT Runtime)
119 |
120 | foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
121 | install(FILES "${bundled_library}"
122 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
123 | COMPONENT Runtime)
124 | endforeach(bundled_library)
125 |
126 | # Fully re-copy the assets directory on each build to avoid having stale files
127 | # from a previous install.
128 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
129 | install(CODE "
130 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
131 | " COMPONENT Runtime)
132 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
133 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
134 |
135 | # Install the AOT library on non-Debug builds only.
136 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
137 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
138 | COMPONENT Runtime)
139 | endif()
140 |
--------------------------------------------------------------------------------
/example/linux/flutter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This file controls Flutter-level build steps. It should not be edited.
2 | cmake_minimum_required(VERSION 3.10)
3 |
4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
5 |
6 | # Configuration provided via flutter tool.
7 | include(${EPHEMERAL_DIR}/generated_config.cmake)
8 |
9 | # TODO: Move the rest of this into files in ephemeral. See
10 | # https://github.com/flutter/flutter/issues/57146.
11 |
12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...),
13 | # which isn't available in 3.10.
14 | function(list_prepend LIST_NAME PREFIX)
15 | set(NEW_LIST "")
16 | foreach(element ${${LIST_NAME}})
17 | list(APPEND NEW_LIST "${PREFIX}${element}")
18 | endforeach(element)
19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
20 | endfunction()
21 |
22 | # === Flutter Library ===
23 | # System-level dependencies.
24 | find_package(PkgConfig REQUIRED)
25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
28 |
29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
30 |
31 | # Published to parent scope for install step.
32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
36 |
37 | list(APPEND FLUTTER_LIBRARY_HEADERS
38 | "fl_basic_message_channel.h"
39 | "fl_binary_codec.h"
40 | "fl_binary_messenger.h"
41 | "fl_dart_project.h"
42 | "fl_engine.h"
43 | "fl_json_message_codec.h"
44 | "fl_json_method_codec.h"
45 | "fl_message_codec.h"
46 | "fl_method_call.h"
47 | "fl_method_channel.h"
48 | "fl_method_codec.h"
49 | "fl_method_response.h"
50 | "fl_plugin_registrar.h"
51 | "fl_plugin_registry.h"
52 | "fl_standard_message_codec.h"
53 | "fl_standard_method_codec.h"
54 | "fl_string_codec.h"
55 | "fl_value.h"
56 | "fl_view.h"
57 | "flutter_linux.h"
58 | )
59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
60 | add_library(flutter INTERFACE)
61 | target_include_directories(flutter INTERFACE
62 | "${EPHEMERAL_DIR}"
63 | )
64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
65 | target_link_libraries(flutter INTERFACE
66 | PkgConfig::GTK
67 | PkgConfig::GLIB
68 | PkgConfig::GIO
69 | )
70 | add_dependencies(flutter flutter_assemble)
71 |
72 | # === Flutter tool backend ===
73 | # _phony_ is a non-existent file to force this command to run every time,
74 | # since currently there's no way to get a full input/output list from the
75 | # flutter tool.
76 | add_custom_command(
77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_
79 | COMMAND ${CMAKE_COMMAND} -E env
80 | ${FLUTTER_TOOL_ENVIRONMENT}
81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
83 | VERBATIM
84 | )
85 | add_custom_target(flutter_assemble DEPENDS
86 | "${FLUTTER_LIBRARY}"
87 | ${FLUTTER_LIBRARY_HEADERS}
88 | )
89 |
--------------------------------------------------------------------------------
/example/linux/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 |
10 | void fl_register_plugins(FlPluginRegistry* registry) {
11 | }
12 |
--------------------------------------------------------------------------------
/example/linux/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void fl_register_plugins(FlPluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/example/linux/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | )
7 |
8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
9 | )
10 |
11 | set(PLUGIN_BUNDLED_LIBRARIES)
12 |
13 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
18 | endforeach(plugin)
19 |
20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
23 | endforeach(ffi_plugin)
24 |
--------------------------------------------------------------------------------
/example/linux/main.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | int main(int argc, char** argv) {
4 | g_autoptr(MyApplication) app = my_application_new();
5 | return g_application_run(G_APPLICATION(app), argc, argv);
6 | }
7 |
--------------------------------------------------------------------------------
/example/linux/my_application.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | #include
4 | #ifdef GDK_WINDOWING_X11
5 | #include
6 | #endif
7 |
8 | #include "flutter/generated_plugin_registrant.h"
9 |
10 | struct _MyApplication {
11 | GtkApplication parent_instance;
12 | char** dart_entrypoint_arguments;
13 | };
14 |
15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
16 |
17 | // Implements GApplication::activate.
18 | static void my_application_activate(GApplication* application) {
19 | MyApplication* self = MY_APPLICATION(application);
20 | GtkWindow* window =
21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
22 |
23 | // Use a header bar when running in GNOME as this is the common style used
24 | // by applications and is the setup most users will be using (e.g. Ubuntu
25 | // desktop).
26 | // If running on X and not using GNOME then just use a traditional title bar
27 | // in case the window manager does more exotic layout, e.g. tiling.
28 | // If running on Wayland assume the header bar will work (may need changing
29 | // if future cases occur).
30 | gboolean use_header_bar = TRUE;
31 | #ifdef GDK_WINDOWING_X11
32 | GdkScreen* screen = gtk_window_get_screen(window);
33 | if (GDK_IS_X11_SCREEN(screen)) {
34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
36 | use_header_bar = FALSE;
37 | }
38 | }
39 | #endif
40 | if (use_header_bar) {
41 | GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
42 | gtk_widget_show(GTK_WIDGET(header_bar));
43 | gtk_header_bar_set_title(header_bar, "example");
44 | gtk_header_bar_set_show_close_button(header_bar, TRUE);
45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
46 | } else {
47 | gtk_window_set_title(window, "example");
48 | }
49 |
50 | gtk_window_set_default_size(window, 550, 650);
51 | gtk_widget_show(GTK_WIDGET(window));
52 |
53 | g_autoptr(FlDartProject) project = fl_dart_project_new();
54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
55 |
56 | FlView* view = fl_view_new(project);
57 | gtk_widget_show(GTK_WIDGET(view));
58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
59 |
60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view));
61 |
62 | gtk_widget_grab_focus(GTK_WIDGET(view));
63 | }
64 |
65 | // Implements GApplication::local_command_line.
66 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
67 | MyApplication* self = MY_APPLICATION(application);
68 | // Strip out the first argument as it is the binary name.
69 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
70 |
71 | g_autoptr(GError) error = nullptr;
72 | if (!g_application_register(application, nullptr, &error)) {
73 | g_warning("Failed to register: %s", error->message);
74 | *exit_status = 1;
75 | return TRUE;
76 | }
77 |
78 | g_application_activate(application);
79 | *exit_status = 0;
80 |
81 | return TRUE;
82 | }
83 |
84 | // Implements GObject::dispose.
85 | static void my_application_dispose(GObject* object) {
86 | MyApplication* self = MY_APPLICATION(object);
87 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
88 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
89 | }
90 |
91 | static void my_application_class_init(MyApplicationClass* klass) {
92 | G_APPLICATION_CLASS(klass)->activate = my_application_activate;
93 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
94 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
95 | }
96 |
97 | static void my_application_init(MyApplication* self) {}
98 |
99 | MyApplication* my_application_new() {
100 | return MY_APPLICATION(g_object_new(my_application_get_type(),
101 | "application-id", APPLICATION_ID,
102 | "flags", G_APPLICATION_NON_UNIQUE,
103 | nullptr));
104 | }
105 |
--------------------------------------------------------------------------------
/example/linux/my_application.h:
--------------------------------------------------------------------------------
1 | #ifndef FLUTTER_MY_APPLICATION_H_
2 | #define FLUTTER_MY_APPLICATION_H_
3 |
4 | #include
5 |
6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
7 | GtkApplication)
8 |
9 | /**
10 | * my_application_new:
11 | *
12 | * Creates a new Flutter-based application.
13 | *
14 | * Returns: a new #MyApplication.
15 | */
16 | MyApplication* my_application_new();
17 |
18 | #endif // FLUTTER_MY_APPLICATION_H_
19 |
--------------------------------------------------------------------------------
/example/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 |
5 | # Xcode-related
6 | **/dgph
7 | **/xcuserdata/
8 |
--------------------------------------------------------------------------------
/example/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | import FlutterMacOS
6 | import Foundation
7 |
8 |
9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
10 | }
11 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
65 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | @NSApplicationMain
5 | class AppDelegate: FlutterAppDelegate {
6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
7 | return true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "app_icon_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "app_icon_32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "app_icon_32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "app_icon_64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "app_icon_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "app_icon_256.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "app_icon_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "app_icon_512.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "app_icon_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "app_icon_1024.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/AppInfo.xcconfig:
--------------------------------------------------------------------------------
1 | // Application-level settings for the Runner target.
2 | //
3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
4 | // future. If not, the values below would default to using the project name when this becomes a
5 | // 'flutter create' template.
6 |
7 | // The application's name. By default this is also the title of the Flutter window.
8 | PRODUCT_NAME = example
9 |
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example
12 |
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2023 com.example. All rights reserved.
15 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Debug.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Release.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Warnings.xcconfig:
--------------------------------------------------------------------------------
1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
2 | GCC_WARN_UNDECLARED_SELECTOR = YES
3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
6 | CLANG_WARN_PRAGMA_PACK = YES
7 | CLANG_WARN_STRICT_PROTOTYPES = YES
8 | CLANG_WARN_COMMA = YES
9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES
10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
12 | GCC_WARN_SHADOW = YES
13 | CLANG_WARN_UNREACHABLE_CODE = YES
14 |
--------------------------------------------------------------------------------
/example/macos/Runner/DebugProfile.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.cs.allow-jit
8 |
9 | com.apple.security.network.server
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/example/macos/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | $(PRODUCT_COPYRIGHT)
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 |
32 |
33 |
--------------------------------------------------------------------------------
/example/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | class MainFlutterWindow: NSWindow {
5 | override func awakeFromNib() {
6 | let flutterViewController = FlutterViewController()
7 | let windowFrame = self.frame
8 | self.contentViewController = flutterViewController
9 | self.setFrame(windowFrame, display: true)
10 |
11 | RegisterGeneratedPlugins(registry: flutterViewController)
12 |
13 | super.awakeFromNib()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/macos/Runner/Release.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import FlutterMacOS
2 | import Cocoa
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/example/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.13.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.2"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.4.0"
28 | clock:
29 | dependency: transitive
30 | description:
31 | name: clock
32 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.1.2"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.19.1"
44 | cupertino_icons:
45 | dependency: "direct main"
46 | description:
47 | name: cupertino_icons
48 | sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "1.0.8"
52 | fake_async:
53 | dependency: transitive
54 | description:
55 | name: fake_async
56 | sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
57 | url: "https://pub.dev"
58 | source: hosted
59 | version: "1.3.3"
60 | flutter:
61 | dependency: "direct main"
62 | description: flutter
63 | source: sdk
64 | version: "0.0.0"
65 | flutter_lints:
66 | dependency: "direct dev"
67 | description:
68 | name: flutter_lints
69 | sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
70 | url: "https://pub.dev"
71 | source: hosted
72 | version: "5.0.0"
73 | flutter_test:
74 | dependency: "direct dev"
75 | description: flutter
76 | source: sdk
77 | version: "0.0.0"
78 | leak_tracker:
79 | dependency: transitive
80 | description:
81 | name: leak_tracker
82 | sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
83 | url: "https://pub.dev"
84 | source: hosted
85 | version: "11.0.2"
86 | leak_tracker_flutter_testing:
87 | dependency: transitive
88 | description:
89 | name: leak_tracker_flutter_testing
90 | sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
91 | url: "https://pub.dev"
92 | source: hosted
93 | version: "3.0.10"
94 | leak_tracker_testing:
95 | dependency: transitive
96 | description:
97 | name: leak_tracker_testing
98 | sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
99 | url: "https://pub.dev"
100 | source: hosted
101 | version: "3.0.2"
102 | lints:
103 | dependency: transitive
104 | description:
105 | name: lints
106 | sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
107 | url: "https://pub.dev"
108 | source: hosted
109 | version: "5.1.1"
110 | matcher:
111 | dependency: transitive
112 | description:
113 | name: matcher
114 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
115 | url: "https://pub.dev"
116 | source: hosted
117 | version: "0.12.17"
118 | material_color_utilities:
119 | dependency: transitive
120 | description:
121 | name: material_color_utilities
122 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
123 | url: "https://pub.dev"
124 | source: hosted
125 | version: "0.11.1"
126 | meta:
127 | dependency: transitive
128 | description:
129 | name: meta
130 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
131 | url: "https://pub.dev"
132 | source: hosted
133 | version: "1.16.0"
134 | path:
135 | dependency: transitive
136 | description:
137 | name: path
138 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
139 | url: "https://pub.dev"
140 | source: hosted
141 | version: "1.9.1"
142 | shader_buffers:
143 | dependency: "direct main"
144 | description:
145 | path: ".."
146 | relative: true
147 | source: path
148 | version: "1.1.2"
149 | sky_engine:
150 | dependency: transitive
151 | description: flutter
152 | source: sdk
153 | version: "0.0.0"
154 | source_span:
155 | dependency: transitive
156 | description:
157 | name: source_span
158 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
159 | url: "https://pub.dev"
160 | source: hosted
161 | version: "1.10.1"
162 | stack_trace:
163 | dependency: transitive
164 | description:
165 | name: stack_trace
166 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
167 | url: "https://pub.dev"
168 | source: hosted
169 | version: "1.12.1"
170 | stream_channel:
171 | dependency: transitive
172 | description:
173 | name: stream_channel
174 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
175 | url: "https://pub.dev"
176 | source: hosted
177 | version: "2.1.4"
178 | string_scanner:
179 | dependency: transitive
180 | description:
181 | name: string_scanner
182 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
183 | url: "https://pub.dev"
184 | source: hosted
185 | version: "1.4.1"
186 | term_glyph:
187 | dependency: transitive
188 | description:
189 | name: term_glyph
190 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
191 | url: "https://pub.dev"
192 | source: hosted
193 | version: "1.2.2"
194 | test_api:
195 | dependency: transitive
196 | description:
197 | name: test_api
198 | sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
199 | url: "https://pub.dev"
200 | source: hosted
201 | version: "0.7.6"
202 | vector_math:
203 | dependency: transitive
204 | description:
205 | name: vector_math
206 | sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
207 | url: "https://pub.dev"
208 | source: hosted
209 | version: "2.2.0"
210 | very_good_analysis:
211 | dependency: "direct dev"
212 | description:
213 | name: very_good_analysis
214 | sha256: "1fb637c0022034b1f19ea2acb42a3603cbd8314a470646a59a2fb01f5f3a8629"
215 | url: "https://pub.dev"
216 | source: hosted
217 | version: "6.0.0"
218 | vm_service:
219 | dependency: transitive
220 | description:
221 | name: vm_service
222 | sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
223 | url: "https://pub.dev"
224 | source: hosted
225 | version: "15.0.2"
226 | sdks:
227 | dart: ">=3.8.0-0 <4.0.0"
228 | flutter: ">=3.18.0-18.0.pre.54"
229 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: shader_buffers_example
2 | description: Shader buffers example
3 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
4 |
5 | version: 1.0.0+1
6 |
7 | environment:
8 | sdk: '>=3.1.5 <4.0.0'
9 |
10 | dependencies:
11 | cupertino_icons: ^1.0.8
12 |
13 | flutter:
14 | sdk: flutter
15 |
16 | shader_buffers:
17 | path: ../
18 |
19 | dev_dependencies:
20 | flutter_lints: ^5.0.0
21 |
22 | flutter_test:
23 | sdk: flutter
24 |
25 | very_good_analysis: ^6.0.0
26 |
27 | flutter:
28 | uses-material-design: true
29 |
30 | assets:
31 | - assets/
32 |
33 | shaders:
34 | - assets/shaders/arrows.frag
35 | - assets/shaders/mouse1.frag
36 | - assets/shaders/mouse2.frag
37 | - assets/shaders/shader1_main.frag
38 | - assets/shaders/shader1_bufferA.frag
39 | - assets/shaders/shader2_main.frag
40 | - assets/shaders/shader2_bufferA.frag
41 | - assets/shaders/test.frag
42 | - assets/shaders/water.frag
43 | - assets/shaders/page_curl.frag
44 | - assets/shaders/noise_fade.frag
45 | - assets/shaders/ripple.frag
46 | - assets/shaders/test_isself_buffer_a.frag
47 | - assets/shaders/test_isself_main.frag
48 | - assets/shaders/filters/black.frag
49 | - assets/shaders/filters/white.frag
50 |
51 |
--------------------------------------------------------------------------------
/example/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/web/favicon.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/web/icons/Icon-maskable-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/web/icons/Icon-maskable-512.png
--------------------------------------------------------------------------------
/example/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | example
33 |
34 |
35 |
39 |
40 |
41 |
42 |
43 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/example/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "short_name": "example",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "icons/Icon-maskable-192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "maskable"
27 | },
28 | {
29 | "src": "icons/Icon-maskable-512.png",
30 | "sizes": "512x512",
31 | "type": "image/png",
32 | "purpose": "maskable"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/example/windows/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral/
2 |
3 | # Visual Studio user-specific files.
4 | *.suo
5 | *.user
6 | *.userosscache
7 | *.sln.docstates
8 |
9 | # Visual Studio build-related files.
10 | x64/
11 | x86/
12 |
13 | # Visual Studio cache files
14 | # files ending in .cache can be ignored
15 | *.[Cc]ache
16 | # but keep track of directories ending in .cache
17 | !*.[Cc]ache/
18 |
--------------------------------------------------------------------------------
/example/windows/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Project-level configuration.
2 | cmake_minimum_required(VERSION 3.14)
3 | project(example LANGUAGES CXX)
4 |
5 | # The name of the executable created for the application. Change this to change
6 | # the on-disk name of your application.
7 | set(BINARY_NAME "example")
8 |
9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
10 | # versions of CMake.
11 | cmake_policy(VERSION 3.14...3.25)
12 |
13 | # Define build configuration option.
14 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
15 | if(IS_MULTICONFIG)
16 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
17 | CACHE STRING "" FORCE)
18 | else()
19 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
20 | set(CMAKE_BUILD_TYPE "Debug" CACHE
21 | STRING "Flutter build mode" FORCE)
22 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
23 | "Debug" "Profile" "Release")
24 | endif()
25 | endif()
26 | # Define settings for the Profile build mode.
27 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
28 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
29 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
30 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
31 |
32 | # Use Unicode for all projects.
33 | add_definitions(-DUNICODE -D_UNICODE)
34 |
35 | # Compilation settings that should be applied to most targets.
36 | #
37 | # Be cautious about adding new options here, as plugins use this function by
38 | # default. In most cases, you should add new options to specific targets instead
39 | # of modifying this function.
40 | function(APPLY_STANDARD_SETTINGS TARGET)
41 | target_compile_features(${TARGET} PUBLIC cxx_std_17)
42 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
43 | target_compile_options(${TARGET} PRIVATE /EHsc)
44 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
45 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>")
46 | endfunction()
47 |
48 | # Flutter library and tool build rules.
49 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
50 | add_subdirectory(${FLUTTER_MANAGED_DIR})
51 |
52 | # Application build; see runner/CMakeLists.txt.
53 | add_subdirectory("runner")
54 |
55 |
56 | # Generated plugin build rules, which manage building the plugins and adding
57 | # them to the application.
58 | include(flutter/generated_plugins.cmake)
59 |
60 |
61 | # === Installation ===
62 | # Support files are copied into place next to the executable, so that it can
63 | # run in place. This is done instead of making a separate bundle (as on Linux)
64 | # so that building and running from within Visual Studio will work.
65 | set(BUILD_BUNDLE_DIR "$")
66 | # Make the "install" step default, as it's required to run.
67 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
68 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
69 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
70 | endif()
71 |
72 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
73 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
74 |
75 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
76 | COMPONENT Runtime)
77 |
78 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
79 | COMPONENT Runtime)
80 |
81 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
82 | COMPONENT Runtime)
83 |
84 | if(PLUGIN_BUNDLED_LIBRARIES)
85 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
86 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
87 | COMPONENT Runtime)
88 | endif()
89 |
90 | # Fully re-copy the assets directory on each build to avoid having stale files
91 | # from a previous install.
92 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
93 | install(CODE "
94 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
95 | " COMPONENT Runtime)
96 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
97 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
98 |
99 | # Install the AOT library on non-Debug builds only.
100 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
101 | CONFIGURATIONS Profile;Release
102 | COMPONENT Runtime)
103 |
--------------------------------------------------------------------------------
/example/windows/flutter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This file controls Flutter-level build steps. It should not be edited.
2 | cmake_minimum_required(VERSION 3.14)
3 |
4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
5 |
6 | # Configuration provided via flutter tool.
7 | include(${EPHEMERAL_DIR}/generated_config.cmake)
8 |
9 | # TODO: Move the rest of this into files in ephemeral. See
10 | # https://github.com/flutter/flutter/issues/57146.
11 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
12 |
13 | # === Flutter Library ===
14 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
15 |
16 | # Published to parent scope for install step.
17 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
18 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
19 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
20 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
21 |
22 | list(APPEND FLUTTER_LIBRARY_HEADERS
23 | "flutter_export.h"
24 | "flutter_windows.h"
25 | "flutter_messenger.h"
26 | "flutter_plugin_registrar.h"
27 | "flutter_texture_registrar.h"
28 | )
29 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
30 | add_library(flutter INTERFACE)
31 | target_include_directories(flutter INTERFACE
32 | "${EPHEMERAL_DIR}"
33 | )
34 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
35 | add_dependencies(flutter flutter_assemble)
36 |
37 | # === Wrapper ===
38 | list(APPEND CPP_WRAPPER_SOURCES_CORE
39 | "core_implementations.cc"
40 | "standard_codec.cc"
41 | )
42 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
43 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
44 | "plugin_registrar.cc"
45 | )
46 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
47 | list(APPEND CPP_WRAPPER_SOURCES_APP
48 | "flutter_engine.cc"
49 | "flutter_view_controller.cc"
50 | )
51 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
52 |
53 | # Wrapper sources needed for a plugin.
54 | add_library(flutter_wrapper_plugin STATIC
55 | ${CPP_WRAPPER_SOURCES_CORE}
56 | ${CPP_WRAPPER_SOURCES_PLUGIN}
57 | )
58 | apply_standard_settings(flutter_wrapper_plugin)
59 | set_target_properties(flutter_wrapper_plugin PROPERTIES
60 | POSITION_INDEPENDENT_CODE ON)
61 | set_target_properties(flutter_wrapper_plugin PROPERTIES
62 | CXX_VISIBILITY_PRESET hidden)
63 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
64 | target_include_directories(flutter_wrapper_plugin PUBLIC
65 | "${WRAPPER_ROOT}/include"
66 | )
67 | add_dependencies(flutter_wrapper_plugin flutter_assemble)
68 |
69 | # Wrapper sources needed for the runner.
70 | add_library(flutter_wrapper_app STATIC
71 | ${CPP_WRAPPER_SOURCES_CORE}
72 | ${CPP_WRAPPER_SOURCES_APP}
73 | )
74 | apply_standard_settings(flutter_wrapper_app)
75 | target_link_libraries(flutter_wrapper_app PUBLIC flutter)
76 | target_include_directories(flutter_wrapper_app PUBLIC
77 | "${WRAPPER_ROOT}/include"
78 | )
79 | add_dependencies(flutter_wrapper_app flutter_assemble)
80 |
81 | # === Flutter tool backend ===
82 | # _phony_ is a non-existent file to force this command to run every time,
83 | # since currently there's no way to get a full input/output list from the
84 | # flutter tool.
85 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
86 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
87 | add_custom_command(
88 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
89 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
90 | ${CPP_WRAPPER_SOURCES_APP}
91 | ${PHONY_OUTPUT}
92 | COMMAND ${CMAKE_COMMAND} -E env
93 | ${FLUTTER_TOOL_ENVIRONMENT}
94 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
95 | windows-x64 $
96 | VERBATIM
97 | )
98 | add_custom_target(flutter_assemble DEPENDS
99 | "${FLUTTER_LIBRARY}"
100 | ${FLUTTER_LIBRARY_HEADERS}
101 | ${CPP_WRAPPER_SOURCES_CORE}
102 | ${CPP_WRAPPER_SOURCES_PLUGIN}
103 | ${CPP_WRAPPER_SOURCES_APP}
104 | )
105 |
--------------------------------------------------------------------------------
/example/windows/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 |
10 | void RegisterPlugins(flutter::PluginRegistry* registry) {
11 | }
12 |
--------------------------------------------------------------------------------
/example/windows/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void RegisterPlugins(flutter::PluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/example/windows/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | )
7 |
8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
9 | )
10 |
11 | set(PLUGIN_BUNDLED_LIBRARIES)
12 |
13 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
18 | endforeach(plugin)
19 |
20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
23 | endforeach(ffi_plugin)
24 |
--------------------------------------------------------------------------------
/example/windows/runner/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.14)
2 | project(runner LANGUAGES CXX)
3 |
4 | # Define the application target. To change its name, change BINARY_NAME in the
5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
6 | # work.
7 | #
8 | # Any new source files that you add to the application should be added here.
9 | add_executable(${BINARY_NAME} WIN32
10 | "flutter_window.cpp"
11 | "main.cpp"
12 | "utils.cpp"
13 | "win32_window.cpp"
14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
15 | "Runner.rc"
16 | "runner.exe.manifest"
17 | )
18 |
19 | # Apply the standard set of build settings. This can be removed for applications
20 | # that need different build settings.
21 | apply_standard_settings(${BINARY_NAME})
22 |
23 | # Add preprocessor definitions for the build version.
24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
29 |
30 | # Disable Windows macros that collide with C++ standard library functions.
31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
32 |
33 | # Add dependency libraries and include directories. Add any application-specific
34 | # dependencies here.
35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
38 |
39 | # Run the Flutter tool portions of the build. This must not be removed.
40 | add_dependencies(${BINARY_NAME} flutter_assemble)
41 |
--------------------------------------------------------------------------------
/example/windows/runner/Runner.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #pragma code_page(65001)
4 | #include "resource.h"
5 |
6 | #define APSTUDIO_READONLY_SYMBOLS
7 | /////////////////////////////////////////////////////////////////////////////
8 | //
9 | // Generated from the TEXTINCLUDE 2 resource.
10 | //
11 | #include "winres.h"
12 |
13 | /////////////////////////////////////////////////////////////////////////////
14 | #undef APSTUDIO_READONLY_SYMBOLS
15 |
16 | /////////////////////////////////////////////////////////////////////////////
17 | // English (United States) resources
18 |
19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""winres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Icon
51 | //
52 |
53 | // Icon with lowest ID value placed first to ensure application icon
54 | // remains consistent on all systems.
55 | IDI_APP_ICON ICON "resources\\app_icon.ico"
56 |
57 |
58 | /////////////////////////////////////////////////////////////////////////////
59 | //
60 | // Version
61 | //
62 |
63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
65 | #else
66 | #define VERSION_AS_NUMBER 1,0,0,0
67 | #endif
68 |
69 | #if defined(FLUTTER_VERSION)
70 | #define VERSION_AS_STRING FLUTTER_VERSION
71 | #else
72 | #define VERSION_AS_STRING "1.0.0"
73 | #endif
74 |
75 | VS_VERSION_INFO VERSIONINFO
76 | FILEVERSION VERSION_AS_NUMBER
77 | PRODUCTVERSION VERSION_AS_NUMBER
78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
79 | #ifdef _DEBUG
80 | FILEFLAGS VS_FF_DEBUG
81 | #else
82 | FILEFLAGS 0x0L
83 | #endif
84 | FILEOS VOS__WINDOWS32
85 | FILETYPE VFT_APP
86 | FILESUBTYPE 0x0L
87 | BEGIN
88 | BLOCK "StringFileInfo"
89 | BEGIN
90 | BLOCK "040904e4"
91 | BEGIN
92 | VALUE "CompanyName", "com.example" "\0"
93 | VALUE "FileDescription", "example" "\0"
94 | VALUE "FileVersion", VERSION_AS_STRING "\0"
95 | VALUE "InternalName", "example" "\0"
96 | VALUE "LegalCopyright", "Copyright (C) 2023 com.example. All rights reserved." "\0"
97 | VALUE "OriginalFilename", "example.exe" "\0"
98 | VALUE "ProductName", "example" "\0"
99 | VALUE "ProductVersion", VERSION_AS_STRING "\0"
100 | END
101 | END
102 | BLOCK "VarFileInfo"
103 | BEGIN
104 | VALUE "Translation", 0x409, 1252
105 | END
106 | END
107 |
108 | #endif // English (United States) resources
109 | /////////////////////////////////////////////////////////////////////////////
110 |
111 |
112 |
113 | #ifndef APSTUDIO_INVOKED
114 | /////////////////////////////////////////////////////////////////////////////
115 | //
116 | // Generated from the TEXTINCLUDE 3 resource.
117 | //
118 |
119 |
120 | /////////////////////////////////////////////////////////////////////////////
121 | #endif // not APSTUDIO_INVOKED
122 |
--------------------------------------------------------------------------------
/example/windows/runner/flutter_window.cpp:
--------------------------------------------------------------------------------
1 | #include "flutter_window.h"
2 |
3 | #include
4 |
5 | #include "flutter/generated_plugin_registrant.h"
6 |
7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project)
8 | : project_(project) {}
9 |
10 | FlutterWindow::~FlutterWindow() {}
11 |
12 | bool FlutterWindow::OnCreate() {
13 | if (!Win32Window::OnCreate()) {
14 | return false;
15 | }
16 |
17 | RECT frame = GetClientArea();
18 |
19 | // The size here must match the window dimensions to avoid unnecessary surface
20 | // creation / destruction in the startup path.
21 | flutter_controller_ = std::make_unique(
22 | frame.right - frame.left, frame.bottom - frame.top, project_);
23 | // Ensure that basic setup of the controller was successful.
24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) {
25 | return false;
26 | }
27 | RegisterPlugins(flutter_controller_->engine());
28 | SetChildContent(flutter_controller_->view()->GetNativeWindow());
29 |
30 | flutter_controller_->engine()->SetNextFrameCallback([&]() {
31 | this->Show();
32 | });
33 |
34 | // Flutter can complete the first frame before the "show window" callback is
35 | // registered. The following call ensures a frame is pending to ensure the
36 | // window is shown. It is a no-op if the first frame hasn't completed yet.
37 | flutter_controller_->ForceRedraw();
38 |
39 | return true;
40 | }
41 |
42 | void FlutterWindow::OnDestroy() {
43 | if (flutter_controller_) {
44 | flutter_controller_ = nullptr;
45 | }
46 |
47 | Win32Window::OnDestroy();
48 | }
49 |
50 | LRESULT
51 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
52 | WPARAM const wparam,
53 | LPARAM const lparam) noexcept {
54 | // Give Flutter, including plugins, an opportunity to handle window messages.
55 | if (flutter_controller_) {
56 | std::optional result =
57 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
58 | lparam);
59 | if (result) {
60 | return *result;
61 | }
62 | }
63 |
64 | switch (message) {
65 | case WM_FONTCHANGE:
66 | flutter_controller_->engine()->ReloadSystemFonts();
67 | break;
68 | }
69 |
70 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
71 | }
72 |
--------------------------------------------------------------------------------
/example/windows/runner/flutter_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_FLUTTER_WINDOW_H_
2 | #define RUNNER_FLUTTER_WINDOW_H_
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include "win32_window.h"
10 |
11 | // A window that does nothing but host a Flutter view.
12 | class FlutterWindow : public Win32Window {
13 | public:
14 | // Creates a new FlutterWindow hosting a Flutter view running |project|.
15 | explicit FlutterWindow(const flutter::DartProject& project);
16 | virtual ~FlutterWindow();
17 |
18 | protected:
19 | // Win32Window:
20 | bool OnCreate() override;
21 | void OnDestroy() override;
22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
23 | LPARAM const lparam) noexcept override;
24 |
25 | private:
26 | // The project to run.
27 | flutter::DartProject project_;
28 |
29 | // The Flutter instance hosted by this window.
30 | std::unique_ptr flutter_controller_;
31 | };
32 |
33 | #endif // RUNNER_FLUTTER_WINDOW_H_
34 |
--------------------------------------------------------------------------------
/example/windows/runner/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "flutter_window.h"
6 | #include "utils.h"
7 |
8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
9 | _In_ wchar_t *command_line, _In_ int show_command) {
10 | // Attach to console when present (e.g., 'flutter run') or create a
11 | // new console when running with a debugger.
12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
13 | CreateAndAttachConsole();
14 | }
15 |
16 | // Initialize COM, so that it is available for use in the library and/or
17 | // plugins.
18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
19 |
20 | flutter::DartProject project(L"data");
21 |
22 | std::vector command_line_arguments =
23 | GetCommandLineArguments();
24 |
25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
26 |
27 | FlutterWindow window(project);
28 | Win32Window::Point origin(10, 10);
29 | Win32Window::Size size(1280, 720);
30 | if (!window.Create(L"example", origin, size)) {
31 | return EXIT_FAILURE;
32 | }
33 | window.SetQuitOnClose(true);
34 |
35 | ::MSG msg;
36 | while (::GetMessage(&msg, nullptr, 0, 0)) {
37 | ::TranslateMessage(&msg);
38 | ::DispatchMessage(&msg);
39 | }
40 |
41 | ::CoUninitialize();
42 | return EXIT_SUCCESS;
43 | }
44 |
--------------------------------------------------------------------------------
/example/windows/runner/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by Runner.rc
4 | //
5 | #define IDI_APP_ICON 101
6 |
7 | // Next default values for new objects
8 | //
9 | #ifdef APSTUDIO_INVOKED
10 | #ifndef APSTUDIO_READONLY_SYMBOLS
11 | #define _APS_NEXT_RESOURCE_VALUE 102
12 | #define _APS_NEXT_COMMAND_VALUE 40001
13 | #define _APS_NEXT_CONTROL_VALUE 1001
14 | #define _APS_NEXT_SYMED_VALUE 101
15 | #endif
16 | #endif
17 |
--------------------------------------------------------------------------------
/example/windows/runner/resources/app_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/example/windows/runner/resources/app_icon.ico
--------------------------------------------------------------------------------
/example/windows/runner/runner.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PerMonitorV2
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/example/windows/runner/utils.cpp:
--------------------------------------------------------------------------------
1 | #include "utils.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | void CreateAndAttachConsole() {
11 | if (::AllocConsole()) {
12 | FILE *unused;
13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
14 | _dup2(_fileno(stdout), 1);
15 | }
16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
17 | _dup2(_fileno(stdout), 2);
18 | }
19 | std::ios::sync_with_stdio();
20 | FlutterDesktopResyncOutputStreams();
21 | }
22 | }
23 |
24 | std::vector GetCommandLineArguments() {
25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
26 | int argc;
27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
28 | if (argv == nullptr) {
29 | return std::vector();
30 | }
31 |
32 | std::vector command_line_arguments;
33 |
34 | // Skip the first argument as it's the binary name.
35 | for (int i = 1; i < argc; i++) {
36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
37 | }
38 |
39 | ::LocalFree(argv);
40 |
41 | return command_line_arguments;
42 | }
43 |
44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) {
45 | if (utf16_string == nullptr) {
46 | return std::string();
47 | }
48 | int target_length = ::WideCharToMultiByte(
49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
50 | -1, nullptr, 0, nullptr, nullptr)
51 | -1; // remove the trailing null character
52 | int input_length = (int)wcslen(utf16_string);
53 | std::string utf8_string;
54 | if (target_length <= 0 || target_length > utf8_string.max_size()) {
55 | return utf8_string;
56 | }
57 | utf8_string.resize(target_length);
58 | int converted_length = ::WideCharToMultiByte(
59 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
60 | input_length, utf8_string.data(), target_length, nullptr, nullptr);
61 | if (converted_length == 0) {
62 | return std::string();
63 | }
64 | return utf8_string;
65 | }
66 |
--------------------------------------------------------------------------------
/example/windows/runner/utils.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_UTILS_H_
2 | #define RUNNER_UTILS_H_
3 |
4 | #include
5 | #include
6 |
7 | // Creates a console for the process, and redirects stdout and stderr to
8 | // it for both the runner and the Flutter library.
9 | void CreateAndAttachConsole();
10 |
11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
12 | // encoded in UTF-8. Returns an empty std::string on failure.
13 | std::string Utf8FromUtf16(const wchar_t* utf16_string);
14 |
15 | // Gets the command line arguments passed in as a std::vector,
16 | // encoded in UTF-8. Returns an empty std::vector on failure.
17 | std::vector GetCommandLineArguments();
18 |
19 | #endif // RUNNER_UTILS_H_
20 |
--------------------------------------------------------------------------------
/example/windows/runner/win32_window.cpp:
--------------------------------------------------------------------------------
1 | #include "win32_window.h"
2 |
3 | #include
4 | #include
5 |
6 | #include "resource.h"
7 |
8 | namespace {
9 |
10 | /// Window attribute that enables dark mode window decorations.
11 | ///
12 | /// Redefined in case the developer's machine has a Windows SDK older than
13 | /// version 10.0.22000.0.
14 | /// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
15 | #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
16 | #define DWMWA_USE_IMMERSIVE_DARK_MODE 20
17 | #endif
18 |
19 | constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
20 |
21 | /// Registry key for app theme preference.
22 | ///
23 | /// A value of 0 indicates apps should use dark mode. A non-zero or missing
24 | /// value indicates apps should use light mode.
25 | constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
26 | L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
27 | constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
28 |
29 | // The number of Win32Window objects that currently exist.
30 | static int g_active_window_count = 0;
31 |
32 | using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
33 |
34 | // Scale helper to convert logical scaler values to physical using passed in
35 | // scale factor
36 | int Scale(int source, double scale_factor) {
37 | return static_cast(source * scale_factor);
38 | }
39 |
40 | // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
41 | // This API is only needed for PerMonitor V1 awareness mode.
42 | void EnableFullDpiSupportIfAvailable(HWND hwnd) {
43 | HMODULE user32_module = LoadLibraryA("User32.dll");
44 | if (!user32_module) {
45 | return;
46 | }
47 | auto enable_non_client_dpi_scaling =
48 | reinterpret_cast(
49 | GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
50 | if (enable_non_client_dpi_scaling != nullptr) {
51 | enable_non_client_dpi_scaling(hwnd);
52 | }
53 | FreeLibrary(user32_module);
54 | }
55 |
56 | } // namespace
57 |
58 | // Manages the Win32Window's window class registration.
59 | class WindowClassRegistrar {
60 | public:
61 | ~WindowClassRegistrar() = default;
62 |
63 | // Returns the singleton registrar instance.
64 | static WindowClassRegistrar* GetInstance() {
65 | if (!instance_) {
66 | instance_ = new WindowClassRegistrar();
67 | }
68 | return instance_;
69 | }
70 |
71 | // Returns the name of the window class, registering the class if it hasn't
72 | // previously been registered.
73 | const wchar_t* GetWindowClass();
74 |
75 | // Unregisters the window class. Should only be called if there are no
76 | // instances of the window.
77 | void UnregisterWindowClass();
78 |
79 | private:
80 | WindowClassRegistrar() = default;
81 |
82 | static WindowClassRegistrar* instance_;
83 |
84 | bool class_registered_ = false;
85 | };
86 |
87 | WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
88 |
89 | const wchar_t* WindowClassRegistrar::GetWindowClass() {
90 | if (!class_registered_) {
91 | WNDCLASS window_class{};
92 | window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
93 | window_class.lpszClassName = kWindowClassName;
94 | window_class.style = CS_HREDRAW | CS_VREDRAW;
95 | window_class.cbClsExtra = 0;
96 | window_class.cbWndExtra = 0;
97 | window_class.hInstance = GetModuleHandle(nullptr);
98 | window_class.hIcon =
99 | LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
100 | window_class.hbrBackground = 0;
101 | window_class.lpszMenuName = nullptr;
102 | window_class.lpfnWndProc = Win32Window::WndProc;
103 | RegisterClass(&window_class);
104 | class_registered_ = true;
105 | }
106 | return kWindowClassName;
107 | }
108 |
109 | void WindowClassRegistrar::UnregisterWindowClass() {
110 | UnregisterClass(kWindowClassName, nullptr);
111 | class_registered_ = false;
112 | }
113 |
114 | Win32Window::Win32Window() {
115 | ++g_active_window_count;
116 | }
117 |
118 | Win32Window::~Win32Window() {
119 | --g_active_window_count;
120 | Destroy();
121 | }
122 |
123 | bool Win32Window::Create(const std::wstring& title,
124 | const Point& origin,
125 | const Size& size) {
126 | Destroy();
127 |
128 | const wchar_t* window_class =
129 | WindowClassRegistrar::GetInstance()->GetWindowClass();
130 |
131 | const POINT target_point = {static_cast(origin.x),
132 | static_cast(origin.y)};
133 | HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
134 | UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
135 | double scale_factor = dpi / 96.0;
136 |
137 | HWND window = CreateWindow(
138 | window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
139 | Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
140 | Scale(size.width, scale_factor), Scale(size.height, scale_factor),
141 | nullptr, nullptr, GetModuleHandle(nullptr), this);
142 |
143 | if (!window) {
144 | return false;
145 | }
146 |
147 | UpdateTheme(window);
148 |
149 | return OnCreate();
150 | }
151 |
152 | bool Win32Window::Show() {
153 | return ShowWindow(window_handle_, SW_SHOWNORMAL);
154 | }
155 |
156 | // static
157 | LRESULT CALLBACK Win32Window::WndProc(HWND const window,
158 | UINT const message,
159 | WPARAM const wparam,
160 | LPARAM const lparam) noexcept {
161 | if (message == WM_NCCREATE) {
162 | auto window_struct = reinterpret_cast(lparam);
163 | SetWindowLongPtr(window, GWLP_USERDATA,
164 | reinterpret_cast(window_struct->lpCreateParams));
165 |
166 | auto that = static_cast(window_struct->lpCreateParams);
167 | EnableFullDpiSupportIfAvailable(window);
168 | that->window_handle_ = window;
169 | } else if (Win32Window* that = GetThisFromHandle(window)) {
170 | return that->MessageHandler(window, message, wparam, lparam);
171 | }
172 |
173 | return DefWindowProc(window, message, wparam, lparam);
174 | }
175 |
176 | LRESULT
177 | Win32Window::MessageHandler(HWND hwnd,
178 | UINT const message,
179 | WPARAM const wparam,
180 | LPARAM const lparam) noexcept {
181 | switch (message) {
182 | case WM_DESTROY:
183 | window_handle_ = nullptr;
184 | Destroy();
185 | if (quit_on_close_) {
186 | PostQuitMessage(0);
187 | }
188 | return 0;
189 |
190 | case WM_DPICHANGED: {
191 | auto newRectSize = reinterpret_cast(lparam);
192 | LONG newWidth = newRectSize->right - newRectSize->left;
193 | LONG newHeight = newRectSize->bottom - newRectSize->top;
194 |
195 | SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
196 | newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
197 |
198 | return 0;
199 | }
200 | case WM_SIZE: {
201 | RECT rect = GetClientArea();
202 | if (child_content_ != nullptr) {
203 | // Size and position the child window.
204 | MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
205 | rect.bottom - rect.top, TRUE);
206 | }
207 | return 0;
208 | }
209 |
210 | case WM_ACTIVATE:
211 | if (child_content_ != nullptr) {
212 | SetFocus(child_content_);
213 | }
214 | return 0;
215 |
216 | case WM_DWMCOLORIZATIONCOLORCHANGED:
217 | UpdateTheme(hwnd);
218 | return 0;
219 | }
220 |
221 | return DefWindowProc(window_handle_, message, wparam, lparam);
222 | }
223 |
224 | void Win32Window::Destroy() {
225 | OnDestroy();
226 |
227 | if (window_handle_) {
228 | DestroyWindow(window_handle_);
229 | window_handle_ = nullptr;
230 | }
231 | if (g_active_window_count == 0) {
232 | WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
233 | }
234 | }
235 |
236 | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
237 | return reinterpret_cast(
238 | GetWindowLongPtr(window, GWLP_USERDATA));
239 | }
240 |
241 | void Win32Window::SetChildContent(HWND content) {
242 | child_content_ = content;
243 | SetParent(content, window_handle_);
244 | RECT frame = GetClientArea();
245 |
246 | MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
247 | frame.bottom - frame.top, true);
248 |
249 | SetFocus(child_content_);
250 | }
251 |
252 | RECT Win32Window::GetClientArea() {
253 | RECT frame;
254 | GetClientRect(window_handle_, &frame);
255 | return frame;
256 | }
257 |
258 | HWND Win32Window::GetHandle() {
259 | return window_handle_;
260 | }
261 |
262 | void Win32Window::SetQuitOnClose(bool quit_on_close) {
263 | quit_on_close_ = quit_on_close;
264 | }
265 |
266 | bool Win32Window::OnCreate() {
267 | // No-op; provided for subclasses.
268 | return true;
269 | }
270 |
271 | void Win32Window::OnDestroy() {
272 | // No-op; provided for subclasses.
273 | }
274 |
275 | void Win32Window::UpdateTheme(HWND const window) {
276 | DWORD light_mode;
277 | DWORD light_mode_size = sizeof(light_mode);
278 | LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
279 | kGetPreferredBrightnessRegValue,
280 | RRF_RT_REG_DWORD, nullptr, &light_mode,
281 | &light_mode_size);
282 |
283 | if (result == ERROR_SUCCESS) {
284 | BOOL enable_dark_mode = light_mode == 0;
285 | DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
286 | &enable_dark_mode, sizeof(enable_dark_mode));
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/example/windows/runner/win32_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_WIN32_WINDOW_H_
2 | #define RUNNER_WIN32_WINDOW_H_
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be
11 | // inherited from by classes that wish to specialize with custom
12 | // rendering and input handling
13 | class Win32Window {
14 | public:
15 | struct Point {
16 | unsigned int x;
17 | unsigned int y;
18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {}
19 | };
20 |
21 | struct Size {
22 | unsigned int width;
23 | unsigned int height;
24 | Size(unsigned int width, unsigned int height)
25 | : width(width), height(height) {}
26 | };
27 |
28 | Win32Window();
29 | virtual ~Win32Window();
30 |
31 | // Creates a win32 window with |title| that is positioned and sized using
32 | // |origin| and |size|. New windows are created on the default monitor. Window
33 | // sizes are specified to the OS in physical pixels, hence to ensure a
34 | // consistent size this function will scale the inputted width and height as
35 | // as appropriate for the default monitor. The window is invisible until
36 | // |Show| is called. Returns true if the window was created successfully.
37 | bool Create(const std::wstring& title, const Point& origin, const Size& size);
38 |
39 | // Show the current window. Returns true if the window was successfully shown.
40 | bool Show();
41 |
42 | // Release OS resources associated with window.
43 | void Destroy();
44 |
45 | // Inserts |content| into the window tree.
46 | void SetChildContent(HWND content);
47 |
48 | // Returns the backing Window handle to enable clients to set icon and other
49 | // window properties. Returns nullptr if the window has been destroyed.
50 | HWND GetHandle();
51 |
52 | // If true, closing this window will quit the application.
53 | void SetQuitOnClose(bool quit_on_close);
54 |
55 | // Return a RECT representing the bounds of the current client area.
56 | RECT GetClientArea();
57 |
58 | protected:
59 | // Processes and route salient window messages for mouse handling,
60 | // size change and DPI. Delegates handling of these to member overloads that
61 | // inheriting classes can handle.
62 | virtual LRESULT MessageHandler(HWND window,
63 | UINT const message,
64 | WPARAM const wparam,
65 | LPARAM const lparam) noexcept;
66 |
67 | // Called when CreateAndShow is called, allowing subclass window-related
68 | // setup. Subclasses should return false if setup fails.
69 | virtual bool OnCreate();
70 |
71 | // Called when Destroy is called.
72 | virtual void OnDestroy();
73 |
74 | private:
75 | friend class WindowClassRegistrar;
76 |
77 | // OS callback called by message pump. Handles the WM_NCCREATE message which
78 | // is passed when the non-client area is being created and enables automatic
79 | // non-client DPI scaling so that the non-client area automatically
80 | // responds to changes in DPI. All other messages are handled by
81 | // MessageHandler.
82 | static LRESULT CALLBACK WndProc(HWND const window,
83 | UINT const message,
84 | WPARAM const wparam,
85 | LPARAM const lparam) noexcept;
86 |
87 | // Retrieves a class instance pointer for |window|
88 | static Win32Window* GetThisFromHandle(HWND const window) noexcept;
89 |
90 | // Update the window frame's theme to match the system theme.
91 | static void UpdateTheme(HWND const window);
92 |
93 | bool quit_on_close_ = false;
94 |
95 | // window handle for top level window.
96 | HWND window_handle_ = nullptr;
97 |
98 | // window handle for hosted content.
99 | HWND child_content_ = nullptr;
100 | };
101 |
102 | #endif // RUNNER_WIN32_WINDOW_H_
103 |
--------------------------------------------------------------------------------
/images/shader_buffers.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alnitak/shader_buffers/4e270089a0606f98568e04539edad6ec0caba482/images/shader_buffers.gif
--------------------------------------------------------------------------------
/lib/shader_buffers.dart:
--------------------------------------------------------------------------------
1 | ///
2 | library shader_buffers;
3 |
4 | export 'src/i_channel.dart';
5 | export 'src/layer_buffer.dart';
6 | export 'src/shader_buffers.dart';
7 | export 'src/uniforms.dart';
8 |
--------------------------------------------------------------------------------
/lib/src/custom_child.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: public_member_api_docs
2 |
3 | import 'dart:ui' as ui;
4 |
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter/rendering.dart';
7 | import 'package:shader_buffers/src/i_channel.dart';
8 |
9 | /// Highly inspired from
10 | /// https://github.com/jonahwilliams/flutter_shaders/blob/main/lib/src/animated_sampler.dart
11 | /// by Jonah Williams
12 |
13 | /// RenderBox which allow to store the snapshot of its child
14 | /// into [IChannel.childTexture] to be used as texture.
15 | /// When enable the snapshot is performed otherwise the child
16 | /// acts normal.
17 | class CustomChildBuilder extends SingleChildRenderObjectWidget {
18 | ///
19 | const CustomChildBuilder({
20 | required this.enabled,
21 | required this.layerChannel,
22 | super.child,
23 | super.key,
24 | });
25 |
26 | final bool enabled;
27 | final IChannel layerChannel;
28 |
29 | @override
30 | RenderObject createRenderObject(BuildContext context) {
31 | return _RenderCustomChildWidget(
32 | devicePixelRatio: MediaQuery.devicePixelRatioOf(context),
33 | layerChannel: layerChannel,
34 | enabled: enabled,
35 | );
36 | }
37 |
38 | @override
39 | void updateRenderObject(
40 | BuildContext context,
41 | covariant RenderObject renderObject,
42 | ) {
43 | (renderObject as _RenderCustomChildWidget)
44 | ..devicePixelRatio = MediaQuery.devicePixelRatioOf(context)
45 | ..layerChannel = layerChannel
46 | ..enabled = enabled;
47 | }
48 | }
49 |
50 | ///
51 | class _RenderCustomChildWidget extends RenderProxyBox {
52 | ///
53 | _RenderCustomChildWidget({
54 | required double devicePixelRatio,
55 | required IChannel layerChannel,
56 | required bool enabled,
57 | }) : _devicePixelRatio = devicePixelRatio,
58 | _layerChannel = layerChannel,
59 | _enabled = enabled;
60 |
61 | /// The device pixel ratio used to create the child image.
62 | double get devicePixelRatio => _devicePixelRatio;
63 | double _devicePixelRatio;
64 |
65 | set devicePixelRatio(double value) {
66 | if (value == devicePixelRatio) {
67 | return;
68 | }
69 | _devicePixelRatio = value;
70 | markNeedsCompositedLayerUpdate();
71 | }
72 |
73 | bool get enabled => _enabled;
74 | bool _enabled;
75 |
76 | set enabled(bool value) {
77 | if (value == enabled) {
78 | return;
79 | }
80 | _enabled = value;
81 | markNeedsPaint();
82 | markNeedsCompositingBitsUpdate();
83 | }
84 |
85 | ///
86 | IChannel get layerChannel => _layerChannel;
87 | IChannel _layerChannel;
88 |
89 | set layerChannel(IChannel value) {
90 | if (value == layerChannel) {
91 | return;
92 | }
93 | _layerChannel = value;
94 | markNeedsCompositedLayerUpdate();
95 | }
96 |
97 | @override
98 | bool get isRepaintBoundary => alwaysNeedsCompositing;
99 |
100 | @override
101 | bool get alwaysNeedsCompositing => enabled;
102 |
103 | @override
104 | OffsetLayer updateCompositedLayer({
105 | required covariant _CustomChildLayer? oldLayer,
106 | }) {
107 | final layer = (oldLayer ?? _CustomChildLayer(layerChannel))
108 | ..size = size
109 | ..devicePixelRatio = devicePixelRatio;
110 | return layer;
111 | }
112 |
113 | @override
114 | void paint(PaintingContext context, Offset offset) {
115 | if (size.isEmpty) {
116 | return;
117 | }
118 | assert(!_enabled || offset == Offset.zero, '');
119 | return super.paint(context, offset);
120 | }
121 | }
122 |
123 | /// The layer that creates and save the [ui.Image] into the [layerChannel]
124 | class _CustomChildLayer extends OffsetLayer {
125 | _CustomChildLayer(this._layerChannel);
126 |
127 | ui.Picture? _lastPicture;
128 |
129 | Size get size => _size;
130 | Size _size = Size.zero;
131 |
132 | set size(Size value) {
133 | if (value == size) {
134 | return;
135 | }
136 | _size = value;
137 | markNeedsAddToScene();
138 | }
139 |
140 | double get devicePixelRatio => _devicePixelRatio;
141 | double _devicePixelRatio = 1;
142 |
143 | set devicePixelRatio(double value) {
144 | if (value == devicePixelRatio) {
145 | return;
146 | }
147 | _devicePixelRatio = value;
148 | markNeedsAddToScene();
149 | }
150 |
151 | IChannel get layerChannel => _layerChannel;
152 | IChannel _layerChannel;
153 |
154 | set layerChannel(IChannel value) {
155 | if (value == layerChannel) {
156 | return;
157 | }
158 | _layerChannel = value;
159 | markNeedsAddToScene();
160 | }
161 |
162 | ui.Image _buildChildScene(Rect bounds, double pixelRatio) {
163 | final builder = ui.SceneBuilder();
164 | final transform = Matrix4.diagonal3Values(pixelRatio, pixelRatio, 1);
165 | builder.pushTransform(transform.storage);
166 | addChildrenToScene(builder);
167 | builder.pop();
168 | return builder.build().toImageSync(
169 | (pixelRatio * bounds.width).ceil(),
170 | (pixelRatio * bounds.height).ceil(),
171 | );
172 | }
173 |
174 | @override
175 | void dispose() {
176 | _lastPicture?.dispose();
177 | super.dispose();
178 | }
179 |
180 | @override
181 | void addToScene(ui.SceneBuilder builder) {
182 | if (size.isEmpty) return;
183 | final image = _buildChildScene(
184 | offset & size,
185 | devicePixelRatio,
186 | );
187 | final pictureRecorder = ui.PictureRecorder();
188 | // final canvas =
189 | Canvas(pictureRecorder);
190 | try {
191 | _layerChannel.childTexture = image.clone();
192 | } finally {
193 | image.dispose();
194 | }
195 | final picture = pictureRecorder.endRecording();
196 | _lastPicture?.dispose();
197 | _lastPicture = picture;
198 | builder.addPicture(offset, picture);
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/lib/src/i_channel.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: public_member_api_docs, sort_constructors_first
2 |
3 | import 'dart:ui' as ui;
4 | import 'package:flutter/services.dart';
5 | import 'package:flutter/widgets.dart';
6 | import 'package:shader_buffers/src/layer_buffer.dart';
7 |
8 | /// class to define the kind of channel textures that will
9 | /// be used by [LayerBuffer].
10 | ///
11 | /// Only one of the parameters can be given.
12 | class IChannel {
13 | IChannel({
14 | this.child,
15 | this.buffer,
16 | this.assetsTexturePath,
17 | this.texture,
18 | this.isSelf = false,
19 | }) : assert(
20 | !(!isSelf &&
21 | child != null &&
22 | buffer != null &&
23 | assetsTexturePath != null &&
24 | texture != null),
25 | 'Only [isSelf] or [child] or [buffer] or [assetsTexturePath] '
26 | ' or [texture] must be given!',
27 | );
28 |
29 | /// the widget used by this [IChannel]
30 | final Widget? child;
31 |
32 | /// the assets image if [child] exists
33 | ui.Image? childTexture;
34 |
35 | final bool isSelf;
36 |
37 | /// the buffer used by this [IChannel]
38 | LayerBuffer? buffer;
39 |
40 | /// the assets image path used by this [IChannel]
41 | String? assetsTexturePath;
42 |
43 | /// the assets image if [assetsTexturePath] exists
44 | ui.Image? texture;
45 |
46 | /// all textures loaded?
47 | bool isInited = false;
48 |
49 | // ignore: use_setters_to_change_properties
50 | void updateTexture(ui.Image image) => texture = image;
51 |
52 | /// eventually load textures
53 | Future init() async {
54 | if (isInited) return true;
55 |
56 | isInited = true;
57 |
58 | if (texture != null) return isInited;
59 |
60 | // Load the assets texture
61 | if (assetsTexturePath != null) {
62 | try {
63 | final assetImageByteData = await rootBundle.load(assetsTexturePath!);
64 | final codec = await ui.instantiateImageCodec(
65 | assetImageByteData.buffer.asUint8List(),
66 | );
67 | texture = (await codec.getNextFrame()).image;
68 | } catch (e) {
69 | debugPrint('Error loading assets image! $e');
70 | isInited = false;
71 | }
72 | }
73 |
74 | return isInited;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/src/imouse.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | /// The `iMouse` values to pass to the shader `iMouse` uniform
4 | class IMouse {
5 | /// The pointer position
6 | /// Shows how to use the mouse input (only left button supported):
7 | ///
8 | /// mouse.xy = mouse position during last button down
9 | /// abs(mouse.zw) = mouse position during last button click
10 | /// sign(mouse.z) = button is down
11 | /// sign(mouse.w) = button is clicked
12 | /// https://www.shadertoy.com/view/llySRh
13 | /// https://www.shadertoy.com/view/Mss3zH
14 | IMouse(this.x, this.y, this.z, this.w);
15 |
16 | /// Default values
17 | double x = 1;
18 |
19 | /// Default values
20 | double y = 1;
21 |
22 | /// Default values
23 | double z = 1;
24 |
25 | /// Default values
26 | double w = -1;
27 |
28 | /// Default values
29 | static IMouse zero = IMouse(1, 1, 1, -1);
30 |
31 | @override
32 | String toString() {
33 | return 'x: $x y: $y z: $z w: $w';
34 | }
35 | }
36 |
37 | /// The current pointer state
38 | ///
39 | enum PointerState {
40 | ///
41 | onPointerDown,
42 |
43 | ///
44 | onPointerMove,
45 |
46 | ///
47 | onPointerUp,
48 |
49 | ///
50 | none,
51 | }
52 |
53 | /// Class to control user tap and pan to manage the `vec4 iMouse` uniform
54 | ///
55 | class IMouseController {
56 | /// Controllore to manage the `vec4 iMouse` uniform
57 | IMouseController({
58 | required this.width,
59 | required this.height,
60 | }) : iMouse = IMouse.zero,
61 | startingPos = Offset.zero;
62 |
63 | /// The current [iMouse]
64 | IMouse iMouse;
65 |
66 | /// Get the current [iMouse] normalized to 0-1
67 | IMouse get iMouseNormalized => getIMouseNormalized();
68 |
69 | /// The width of the widget
70 | final double width;
71 |
72 | /// The heigth of the widget
73 | final double height;
74 |
75 | /// The position when the user tap on the shader widget
76 | Offset startingPos;
77 |
78 | /// The current state of mouse interaction
79 | PointerState currState = PointerState.none;
80 |
81 | /// Update [iMouse] when the user starts to pan
82 | void start(Offset position) {
83 | startingPos = position;
84 | iMouse = getIMouseValue(startingPos, PointerState.onPointerDown);
85 | updatePointer(PointerState.onPointerDown);
86 | }
87 |
88 | /// Update [iMouse] when the user pan
89 | void update(Offset position) {
90 | iMouse = getIMouseValue(position, PointerState.onPointerMove);
91 | updatePointer(PointerState.onPointerMove);
92 | }
93 |
94 | /// Update [iMouse] when the user ends to pan
95 | void end() {
96 | iMouse =
97 | getIMouseValue(Offset(iMouse.x, iMouse.y), PointerState.onPointerUp);
98 | updatePointer(PointerState.onPointerUp);
99 | }
100 |
101 | /// Get the iMouse vec4
102 | IMouse getIMouseValue(
103 | Offset pos,
104 | PointerState eventType,
105 | ) {
106 | return IMouse(
107 | pos.dx,
108 | pos.dy,
109 | eventType == PointerState.onPointerDown ||
110 | eventType == PointerState.onPointerMove
111 | ? startingPos.dx
112 | : -startingPos.dx,
113 | -startingPos.dy,
114 | );
115 | }
116 |
117 | /// get the mouse coordinates in the 0~1 range
118 | IMouse getIMouseNormalized() {
119 | return IMouse(
120 | iMouse.x / width,
121 | iMouse.y / height,
122 | (iMouse.w / width).abs(),
123 | (iMouse.z / height).abs(),
124 | );
125 | }
126 |
127 | /// update iMouse when user interact
128 | void updatePointer(PointerState state) {
129 | currState = state;
130 | if (state == PointerState.onPointerUp) {
131 | currState = PointerState.none;
132 | }
133 | }
134 |
135 | @override
136 | String toString() => 'IMouseController(iMouse: $iMouse)';
137 | }
138 |
--------------------------------------------------------------------------------
/lib/src/layer_buffer.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: public_member_api_docs, sort_constructors_first
2 | import 'dart:ui' as ui;
3 | import 'dart:ui';
4 |
5 | import 'package:flutter/services.dart';
6 | import 'package:flutter/widgets.dart';
7 | import 'package:shader_buffers/src/i_channel.dart';
8 |
9 | import 'package:shader_buffers/src/imouse.dart';
10 | import 'package:shader_buffers/src/uniforms.dart';
11 |
12 | /// Class used to define a buffers or the main image layer.
13 | ///
14 | class LayerBuffer {
15 | /// Class used to define a buffers or the main image.
16 | ///
17 | /// It takes the [shaderAssetsName] and a list of [IChannel]
18 | /// used as textures.
19 | ///
20 | /// ```dart
21 | /// final bufferA = LayerBuffer(
22 | /// shaderAssetsName: 'assets/shaders/shader3_bufferA.glsl',
23 | /// );
24 | /// // you can then set optional channels:
25 | /// bufferA.setChannels([
26 | /// IChannel(assetsTexturePath: 'assets/bricks.jpg'),
27 | /// ]);
28 | /// ```
29 | LayerBuffer({
30 | required this.shaderAssetsName,
31 | this.scaleRenderView = 1,
32 | this.uniforms,
33 | }) : assert(scaleRenderView > 0, 'scaleRenderView must be > 0');
34 |
35 | /// The fragment shader source to use
36 | final String shaderAssetsName;
37 |
38 | /// Scale the rendered window.
39 | ///
40 | /// It happens that a shader could be computationally heavy.
41 | /// You can reduce the resolution of the rendered window: by setting
42 | /// [scaleRenderView] to 0.5 for example, you will get a half
43 | /// resolution image. But this could cause pixelation. If you want instead
44 | /// to get a higher resolution image, ie for zooming, you can set the value
45 | /// to 2.
46 | final double scaleRenderView;
47 |
48 | /// additional uniforms
49 | Uniforms? uniforms;
50 |
51 | /// the channels this shader will use
52 | List? channels;
53 |
54 | /// the fragment program used by this layer
55 | ui.FragmentProgram? _program;
56 |
57 | /// the fragment shader used by this layer
58 | ui.FragmentShader? _shader;
59 |
60 | /// The last image computed
61 | ui.Image? layerImage;
62 |
63 | /// Used internally when shader or channel are not yet initialized
64 | ui.Image? blankImage;
65 |
66 | double _deviceAspectRatio = 1;
67 |
68 | List conditionalOperation = [];
69 |
70 | /// set channels of this layer
71 | void setChannels(List chan) {
72 | channels = chan.toList();
73 | }
74 |
75 | /// Initialize the shader and the textures if any
76 | Future init() async {
77 | var loaded = true;
78 | loaded = await _loadShader();
79 | loaded &= await _loadAssetsTextures();
80 | _deviceAspectRatio =
81 | PlatformDispatcher.instance.views.first.devicePixelRatio;
82 | debugPrint('LayerBuffer.init() loaded: $loaded $shaderAssetsName');
83 | return loaded;
84 | }
85 |
86 | /// load fragment shader
87 | Future _loadShader() async {
88 | try {
89 | _program = await ui.FragmentProgram.fromAsset(shaderAssetsName);
90 | _shader = _program?.fragmentShader();
91 | } on Exception catch (e) {
92 | debugPrint('Cannot load shader $shaderAssetsName! $e');
93 | return false;
94 | }
95 | return true;
96 | }
97 |
98 | /// load the blank image and initialize all channel textures
99 | Future _loadAssetsTextures() async {
100 | /// setup blankImage. Displayed when the layerImage is not yet available
101 | try {
102 | final assetImageByteData = await rootBundle
103 | .load('packages/shader_buffers/assets/blank_16x16.bmp');
104 | final codec = await ui.instantiateImageCodec(
105 | assetImageByteData.buffer.asUint8List(),
106 | );
107 | blankImage = (await codec.getNextFrame()).image;
108 | } on Exception catch (e) {
109 | debugPrint('Cannot load blankImage! $e');
110 | return false;
111 | }
112 |
113 | // Load all the assets textures if any
114 | if (channels == null) return true;
115 | for (var i = 0; i < channels!.length; ++i) {
116 | for (final element in channels!) {
117 | if (!element.isInited) {
118 | if (!await channels![i].init()) return false;
119 | }
120 | }
121 | }
122 | return true;
123 | }
124 |
125 | void dispose() {
126 | // _shader?.dispose();
127 | layerImage?.dispose();
128 | layerImage = null;
129 | }
130 |
131 | /// Draw the shader into [layerImage].
132 | ///
133 | /// Using the same [layerImage] of this layer as the input texture,
134 | /// cause a memory leak:
135 | /// https://github.com/flutter/flutter/issues/138627
136 | ///
137 | /// Clear unfreed cached mem on linux
138 | /// sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
139 | void computeLayer(
140 | Size iResolution,
141 | double iTime,
142 | double iFrame,
143 | IMouse iMouse,
144 | ) {
145 | if (_shader == null) return;
146 |
147 | final realPixels = iResolution * _deviceAspectRatio * scaleRenderView;
148 |
149 | _shader!
150 | ..setFloat(0, realPixels.width) // iResolution
151 | ..setFloat(1, realPixels.height)
152 | ..setFloat(2, iTime) // iTime
153 | ..setFloat(3, iFrame) // iFrame
154 | ..setFloat(4, iMouse.x) // iMouse
155 | ..setFloat(5, iMouse.y)
156 | ..setFloat(6, iMouse.z)
157 | ..setFloat(7, iMouse.w);
158 |
159 | /// eventually add more floats uniforms from [floatsUniforms]
160 | for (var i = 0; i < (uniforms?.uniforms.length ?? 0); i++) {
161 | _shader!.setFloat(i + 8, uniforms!.uniforms[i].value);
162 | }
163 |
164 | /// eventually add sampler2D uniforms
165 | for (var i = 0; i < (channels?.length ?? 0); i++) {
166 | if (channels![i].assetsTexturePath != null) {
167 | _shader!.setImageSampler(i, channels![i].texture ?? blankImage!);
168 | } else if (channels![i].child != null) {
169 | _shader!.setImageSampler(i, channels![i].childTexture ?? blankImage!);
170 | } else {
171 | ui.Image? img;
172 | if (channels![i].isSelf) {
173 | img = layerImage ?? blankImage!;
174 | } else {
175 | if (channels![i].buffer?.layerImage == null) {
176 | img = channels![i].texture;
177 | }
178 | }
179 | _shader!.setImageSampler(i, img ?? blankImage!);
180 | }
181 | }
182 |
183 | /// While this issue
184 | /// https://github.com/flutter/flutter/issues/138627
185 | /// is still open, here the [toImage] will be used instead of [toImageSync]
186 | ///
187 | // layerImage?.dispose();
188 | // layerImage = null;
189 |
190 | // final recorder = ui.PictureRecorder();
191 | // ui.Canvas(recorder).drawRect(
192 | // Offset.zero & iResolution,
193 | // ui.Paint()..shader = _shader,
194 | // );
195 | // final picture = recorder.endRecording();
196 | // layerImage = picture.toImageSync(
197 | // iResolution.width.ceil(),
198 | // iResolution.height.ceil(),
199 | // );
200 | // picture.dispose();
201 |
202 | final recorder = ui.PictureRecorder();
203 | ui.Canvas(recorder).drawRect(
204 | Offset.zero & realPixels,
205 | ui.Paint()..shader = _shader,
206 | );
207 | final picture = recorder.endRecording();
208 | picture
209 | .toImage(
210 | realPixels.width.ceil(),
211 | realPixels.height.ceil(),
212 | )
213 | .then((value) => layerImage = value);
214 | picture.dispose();
215 |
216 | for (final f in conditionalOperation) {
217 | f();
218 | }
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/lib/src/uniforms.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: public_member_api_docs
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | /// The uniform class
6 | class Uniform {
7 | Uniform({
8 | required this.value,
9 | required this.name,
10 | required this.range,
11 | required this.defaultValue,
12 | });
13 | final RangeValues range;
14 | final double defaultValue;
15 | final String name;
16 | double value;
17 |
18 | @override
19 | String toString() => 'Uniform [$name]: $value';
20 | }
21 |
22 | /// The uniforms list with method helpers
23 | class Uniforms {
24 | Uniforms(this.uniforms);
25 |
26 | final List uniforms;
27 |
28 | void setValue(String name, double value) {
29 | uniforms.firstWhere((element) => element.name == name).value = value;
30 | }
31 |
32 | double getValue(String name) {
33 | return uniforms.firstWhere((element) => element.name == name).value;
34 | }
35 |
36 | void setValueByIndex(int index, double value) {
37 | assert(
38 | index >= 0 && index < uniforms.length,
39 | 'Uniform index out of range!',
40 | );
41 | uniforms[index].value = value;
42 | }
43 |
44 | double getValueByIndex(int index) {
45 | assert(
46 | index >= 0 && index < uniforms.length,
47 | 'Uniform index out of range!',
48 | );
49 | return uniforms[index].value;
50 | }
51 |
52 | List getDoubleList() {
53 | return List.generate(uniforms.length, (index) => uniforms[index].value);
54 | }
55 |
56 | void setDoubleList(List values) {
57 | assert(values.length == uniforms.length, "Uniform length doesn't match!");
58 | for (var i = 0; i < values.length; i++) {
59 | uniforms[i].value = values[i];
60 | }
61 | }
62 |
63 | Uniform getUniformByName(String name) {
64 | return uniforms.firstWhere((element) => element.name == name);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: shader_buffers
2 | description: >-
3 | Using shaders to feed a shader. Make shaders simplier
4 | to use with a focus on the ShaderToy.com website.
5 | version: 1.1.2
6 | homepage: https://github.com/alnitak/shader_buffers
7 | issue_tracker: https://github.com/alnitak/shader_buffers/issues
8 | repository: https://github.com/alnitak/shader_buffers
9 | topics:
10 | - shader
11 | - shadertoy
12 |
13 | environment:
14 | sdk: '>=3.1.5 <4.0.0'
15 | flutter: ">=1.17.0"
16 |
17 | dependencies:
18 | flutter:
19 | sdk: flutter
20 |
21 | dev_dependencies:
22 | flutter_lints: ^3.0.1
23 |
24 | flutter_test:
25 | sdk: flutter
26 |
27 | very_good_analysis: ^5.1.0
28 |
29 | flutter:
30 |
31 | assets:
32 | - assets/
33 |
34 |
--------------------------------------------------------------------------------
/test/shader_buffers_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_test/flutter_test.dart';
2 |
3 | void main() {
4 | test('adds one to input values', () {});
5 | }
6 |
--------------------------------------------------------------------------------