From b013376c5cf1948ca5806d3ac4343511b67573ff Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Sat, 3 Dec 2022 11:06:43 -0800 Subject: [PATCH 01/16] Add documentation on fragment program API and usage --- src/development/ui/advanced/shaders.md | 178 +++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 src/development/ui/advanced/shaders.md diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md new file mode 100644 index 00000000000..d77ce5ca267 --- /dev/null +++ b/src/development/ui/advanced/shaders.md @@ -0,0 +1,178 @@ +--- +title: Writing and using Fragment Shaders +description: How to author and use fragment shaders. +short-title: Fragment Shaders +--- + +Note: The HTML backend does not support the FragmentProgram API. The CanvasKit backend will support this API in a future release. + +A shader is a program that is executed by the GPU, usually authored in a small, dart-like language such as GLSL. User authored shaders can be incorporated into Flutter applications and packages via the FragmentProgram API. These can be used to provide rich graphical effects beyond those provided by the Flutter SDK. + +## Adding Shaders to an Application + +Shaders must be declared in the new `shaders` section of your application or package pubspec.yaml file. This allows the Flutter command line tool to compile the shader to the appropriate backend format, as well as generate the necessary runtime metadata. When running in debug mode, changes to a shader program will trigger a recompilation and update of the shader during hot reload or hot restart. + +```yaml +flutter: + shaders: + - shaders/myshader.frag +``` + +Shaders from packages can be included using the same technique as other assets. + +#### Loading shaders at runtime + +FragmentPrograms can be loaded at runtime using the FragmentProgram.fromAsset constructor. The key should be the file path specified in the pubspec.yaml above. + +```dart +void loadMyShader() async { + var program = await FragmentProgram.fromAsset('shaders/myshader.frag'); +} +``` + +The FragmentProgram object can be used to create one or more FragmentShader +instances. A FragmentShader represents a particular combination of a +program and bound uniforms. + +```dart +void updateShader(Canvas canvas, Rect rect, FragmentProgram program) { + var shader = program.createShader(); + shader.setFloat(0, 42.0); + canvas.drawRect(rect, Paint()..shader = shader); +} +``` + +## Canvas API + +Fragment shaders can be used with most Canvas APIs that accept either solid +colors or gradients via a [Paint] object. And will cover an area determined +by the geometry of the canvas API used. For example, with a call to +[Canvas.drawRect] the shader will be evaluated for all fragments within +the rectangle. For an API like [Canvas.drawPath] with a stroked path, the +shader will be evaluated for all fragments within the stroked line. Some +APIs such as drawImage ignore the value of the shader. + +```dart +void paint(Canvas canvas, Size size, FragmentShader shader) { + // Draws a rectangle with the shader used as a color source. + canvas.drawRect( + Rect.fromLTWH(0, 0, size.width, size.height), + Paint()..shader = shader, + ); + + // Draws a stroked rectangle with the shader only applied to the fragments + // that lie within the stroke. + canvas.drawRect( + Rect.fromLTWH(0, 0, size.width, size.height), + Paint() + ..style = PaintingStyle.stroke + ..shader = shader, + ) +} + +``` + +## Authoring Shaders + +Shaders are authored as GLSL source files. Any version from 460 down to 100 is supported, though some available features are restricted. For the rest of the examples in this document `460 core` will be used. Notably: + +* UBOs and SSBOs are unsupported. +* `sampler2D` is the only supported sampler type, and only the two argument version of `texture` (sampler and uv) is supported when targeting SkSL. +* Only a position varying is available, and no additional varying may be declared. +* When targeting SkSL, all precision hints are ignored. +* Unsigned integers and booleans are unsupported. + +#### Uniforms + +A fragment program is configured by defining uniform values in the shader source and then setting these values per fragment shader instance. + +Uniforms are set using [FragmentShader.setFloat] or [FragmentShader.setSampler], depending on the type of uniform. Float values includes floats and vec2, vec3, and vec4. Sampler values are only `sampler2D`. + +The correct index for each uniform is determined by the order of the uniforms as defined in the fragment program. For data types that are composed of multiple floats such as a vec4, more than one call to [setFloat] is required. + +For example, given the following uniforms in a fragment program: + +```glsl +uniform float uScale; +uniform sampler2D uTexture; +uniform vec2 uMagnitude; +uniform vec4 uColor; +``` + +Then the corresponding Dart code to correctly initialize these uniforms is: + +```dart +void updateShader(ui.FragmentShader shader, Color color, ui.Image image) { + shader.setFloat(0, 23); // uScale + shader.setFloat(1, 114); // uMagnitude x + shader.setFloat(2, 83); // uMagnitude y + + // Convert color to premultiplied opacity. + shader.setFloat(3, color.red / 255 * color.opacity); // uColor r + shader.setFloat(4, color.green / 255 * color.opacity); // uColor g + shader.setFloat(5, color.blue / 255 * color.opacity); // uColor b + shader.setFloat(6, color.opacity); // uColor a + + // initialize sampler uniform. + shader.setImageSampler(0, image); + } + ``` + +Note how the indexes used does not count the `sampler2D` uniform. This uniform will be set separately with [setImageSampler], with the index starting over at 0. + +Any float uniforms that are left uninitialized will default to `0`. + +#### Current Position + +The shader has access to a varying which contains the local coordinates for the particular fragment that is being evaluated. This can be used to compute effects that depend on the position. This position can be accessed by importing the `flutter/runtime_effect.glsl` library and calling the `FlutterFragCoord` function like below. + +```glsl +#include + +void main() { + vec2 currentPos = FlutterFragCoord().xy; +} +``` + +The value returned from `FlutterFragCoord` is distinct from `gl_FragCoord`. `gl_FragCoord` provides the screen space coordinates and should generally be avoided to ensure shaders are consistent across backends. When targeting a Skia backend the calls to gl_FragCoord are rewritten to access local coordinates but this rewriting is not possible with Impeller. + + +#### Colors + +There is no built-in data type for colors. Instead they are commonly represented as a `vec4` with each component corresponding to one of the RGBA color channels. + +The single output `fragColor` expects that the color value is normalized colors to be in the range of `0.0` to `1.0` and that it has premultiplied alpha. This is different than typical Flutter colors which use a `0-255` value encoding and have +unpremultipled alpha. + +#### Samplers + +A sampler provides access to a dart:ui Image object. This image can be acquired either from a decoded image or from part of the application using [Scene.toImageSync] or [Picture.toImageSync]. + + +```glsl +#include + +uniform vec2 uSize; +uniform sampler2D uTexture; + +out vec4 fragColor; + +void main() { + vec2 uv = FlutterFragCoord().xy / uSize; + fragColor = texture(uTexture, uv); +} +``` + +### Performance Considerations + +When targeting the Skia backend loading the shader may be expensive, since it must be compiled to the appropriate platform specific shader. If you intend to use one or more shaders during an animation, prefer to precache the fragment program objects before starting the animation. + +For a more detailed guide on writing performant shaders, see https://github.com/flutter/engine/blob/main/impeller/docs/shader_optimization.md from the flutter/engine. + + +### Other resources + +For more information, here are a few resources. + +* https://thebookofshaders.com/ +* https://www.shadertoy.com/ From 1f68f6b22fa593d267189a80bbefeb0f4723abdf Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 5 Dec 2022 09:51:01 -0800 Subject: [PATCH 02/16] ++ --- src/development/ui/advanced/shaders.md | 40 +++++++++++++++----------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index d77ce5ca267..4e6d23448f8 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -74,7 +74,7 @@ void paint(Canvas canvas, Size size, FragmentShader shader) { ## Authoring Shaders -Shaders are authored as GLSL source files. Any version from 460 down to 100 is supported, though some available features are restricted. For the rest of the examples in this document `460 core` will be used. Notably: +Shaders are authored as GLSL source files. Any version from 460 down to 100 is supported, though some available features are restricted. For the rest of the examples in this document `460 core` will be used. * UBOs and SSBOs are unsupported. * `sampler2D` is the only supported sampler type, and only the two argument version of `texture` (sampler and uv) is supported when targeting SkSL. @@ -88,7 +88,7 @@ A fragment program is configured by defining uniform values in the shader source Uniforms are set using [FragmentShader.setFloat] or [FragmentShader.setSampler], depending on the type of uniform. Float values includes floats and vec2, vec3, and vec4. Sampler values are only `sampler2D`. -The correct index for each uniform is determined by the order of the uniforms as defined in the fragment program. For data types that are composed of multiple floats such as a vec4, more than one call to [setFloat] is required. +The correct index for each uniform is determined by the order of the uniforms as defined in the fragment program. For data types that are composed of multiple floats such as a vec4, more than one call to [FragmentShader.setFloat] is required. For example, given the following uniforms in a fragment program: @@ -102,23 +102,23 @@ uniform vec4 uColor; Then the corresponding Dart code to correctly initialize these uniforms is: ```dart -void updateShader(ui.FragmentShader shader, Color color, ui.Image image) { - shader.setFloat(0, 23); // uScale - shader.setFloat(1, 114); // uMagnitude x - shader.setFloat(2, 83); // uMagnitude y - - // Convert color to premultiplied opacity. - shader.setFloat(3, color.red / 255 * color.opacity); // uColor r - shader.setFloat(4, color.green / 255 * color.opacity); // uColor g - shader.setFloat(5, color.blue / 255 * color.opacity); // uColor b - shader.setFloat(6, color.opacity); // uColor a - - // initialize sampler uniform. - shader.setImageSampler(0, image); +void updateShader(FragmentShader shader, Color color, Image image) { + shader.setFloat(0, 23); // uScale + shader.setFloat(1, 114); // uMagnitude x + shader.setFloat(2, 83); // uMagnitude y + + // Convert color to premultiplied opacity. + shader.setFloat(3, color.red / 255 * color.opacity); // uColor r + shader.setFloat(4, color.green / 255 * color.opacity); // uColor g + shader.setFloat(5, color.blue / 255 * color.opacity); // uColor b + shader.setFloat(6, color.opacity); // uColor a + + // initialize sampler uniform. + shader.setImageSampler(0, image); } ``` -Note how the indexes used does not count the `sampler2D` uniform. This uniform will be set separately with [setImageSampler], with the index starting over at 0. +Note how the indexes used does not count the `sampler2D` uniform. This uniform will be set separately with [FragmentShader.setImageSampler], with the index starting over at 0. Any float uniforms that are left uninitialized will default to `0`. @@ -148,7 +148,6 @@ unpremultipled alpha. A sampler provides access to a dart:ui Image object. This image can be acquired either from a decoded image or from part of the application using [Scene.toImageSync] or [Picture.toImageSync]. - ```glsl #include @@ -163,6 +162,8 @@ void main() { } ``` +By default, the image uses a clamping address mode. Currently customization of the addressing mode is not supported and needs to be emulated in the shader. + ### Performance Considerations When targeting the Skia backend loading the shader may be expensive, since it must be compiled to the appropriate platform specific shader. If you intend to use one or more shaders during an animation, prefer to precache the fragment program objects before starting the animation. @@ -176,3 +177,8 @@ For more information, here are a few resources. * https://thebookofshaders.com/ * https://www.shadertoy.com/ + +[`Canvas`]: {{site.api}}/flutter/dart-ui/Canvas-class.html +[`Scene`]: {{site.api}}/flutter/dart-ui/Scene-class.html +[`FragmentProgram`]: {{site.api}}/flutter/dart-ui/FragmentProgram-class.html +[`FragmentShader`]: {{site.api}}/flutter/dart-ui/FragmentShader-class.html From 924d471adcbc907bc6db81796b5e8f2841f9b512 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 5 Dec 2022 10:03:57 -0800 Subject: [PATCH 03/16] ++ --- src/development/ui/advanced/shaders.md | 90 +++++++++++++++++++------- 1 file changed, 67 insertions(+), 23 deletions(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 4e6d23448f8..219b9a6c6e3 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -4,13 +4,22 @@ description: How to author and use fragment shaders. short-title: Fragment Shaders --- -Note: The HTML backend does not support the FragmentProgram API. The CanvasKit backend will support this API in a future release. +Note: The HTML backend does not support the FragmentProgram API. The CanvasKit +backend will support this API in a future release. -A shader is a program that is executed by the GPU, usually authored in a small, dart-like language such as GLSL. User authored shaders can be incorporated into Flutter applications and packages via the FragmentProgram API. These can be used to provide rich graphical effects beyond those provided by the Flutter SDK. +A shader is a program that is executed by the GPU, usually authored in a small, +dart-like language such as GLSL. User authored shaders can be incorporated into +Flutter applications and packages via the FragmentProgram API. These can be +used to provide rich graphical effects beyond those provided by the Flutter SDK. ## Adding Shaders to an Application -Shaders must be declared in the new `shaders` section of your application or package pubspec.yaml file. This allows the Flutter command line tool to compile the shader to the appropriate backend format, as well as generate the necessary runtime metadata. When running in debug mode, changes to a shader program will trigger a recompilation and update of the shader during hot reload or hot restart. +Shaders must be declared in the new `shaders` section of your application or +package pubspec.yaml file. This allows the Flutter command line tool to compile +the shader to the appropriate backend format, as well as generate the necessary +runtime metadata. When running in debug mode, changes to a shader program will +trigger a recompilation and update of the shader during hot reload or hot +restart. ```yaml flutter: @@ -22,7 +31,9 @@ Shaders from packages can be included using the same technique as other assets. #### Loading shaders at runtime -FragmentPrograms can be loaded at runtime using the FragmentProgram.fromAsset constructor. The key should be the file path specified in the pubspec.yaml above. +FragmentPrograms can be loaded at runtime using the [FragmentProgram.fromAsset] +constructor. The key should be the file path specified in the pubspec.yaml +above. ```dart void loadMyShader() async { @@ -74,21 +85,31 @@ void paint(Canvas canvas, Size size, FragmentShader shader) { ## Authoring Shaders -Shaders are authored as GLSL source files. Any version from 460 down to 100 is supported, though some available features are restricted. For the rest of the examples in this document `460 core` will be used. +Shaders are authored as GLSL source files. Any version from 460 down to 100 +is supported, though some available features are restricted. For the rest +of the examples in this document `460 core` will be used. * UBOs and SSBOs are unsupported. -* `sampler2D` is the only supported sampler type, and only the two argument version of `texture` (sampler and uv) is supported when targeting SkSL. -* Only a position varying is available, and no additional varying may be declared. -* When targeting SkSL, all precision hints are ignored. +* `sampler2D` is the only supported sampler type +* Only the two argument version of `texture` (sampler and uv) is supported. +* No varyings may be declared. + * Note: A position varying is available for each shader +* All precision hints are ignored when targeting Skia. * Unsigned integers and booleans are unsupported. #### Uniforms -A fragment program is configured by defining uniform values in the shader source and then setting these values per fragment shader instance. +A fragment program is configured by defining uniform values in the shader +source and then setting these values per fragment shader instance. -Uniforms are set using [FragmentShader.setFloat] or [FragmentShader.setSampler], depending on the type of uniform. Float values includes floats and vec2, vec3, and vec4. Sampler values are only `sampler2D`. +Uniforms are set using [FragmentShader.setFloat] or +[FragmentShader.setSampler], depending on the type of uniform. Float values +includes floats and vec2, vec3, and vec4. Sampler values are only `sampler2D`. -The correct index for each uniform is determined by the order of the uniforms as defined in the fragment program. For data types that are composed of multiple floats such as a vec4, more than one call to [FragmentShader.setFloat] is required. +The correct index for each uniform is determined by the order of the uniforms +as defined in the fragment program. For data types that are composed of +multiple floats such as a vec4, more than one call to [FragmentShader.setFloat] +is required. For example, given the following uniforms in a fragment program: @@ -99,7 +120,7 @@ uniform vec2 uMagnitude; uniform vec4 uColor; ``` -Then the corresponding Dart code to correctly initialize these uniforms is: +The corresponding Dart code to correctly initialize these uniforms is: ```dart void updateShader(FragmentShader shader, Color color, Image image) { @@ -118,13 +139,19 @@ void updateShader(FragmentShader shader, Color color, Image image) { } ``` -Note how the indexes used does not count the `sampler2D` uniform. This uniform will be set separately with [FragmentShader.setImageSampler], with the index starting over at 0. +Note how the indexes used does not count the `sampler2D` uniform. This uniform +will be set separately with [FragmentShader.setImageSampler], with the +index starting over at 0. Any float uniforms that are left uninitialized will default to `0`. #### Current Position -The shader has access to a varying which contains the local coordinates for the particular fragment that is being evaluated. This can be used to compute effects that depend on the position. This position can be accessed by importing the `flutter/runtime_effect.glsl` library and calling the `FlutterFragCoord` function like below. +The shader has access to a varying which contains the local coordinates for +the particular fragment that is being evaluated. This can be used to compute +effects that depend on the position. This position can be accessed by +importing the `flutter/runtime_effect.glsl` library and calling the +`FlutterFragCoord` function like below. ```glsl #include @@ -134,19 +161,28 @@ void main() { } ``` -The value returned from `FlutterFragCoord` is distinct from `gl_FragCoord`. `gl_FragCoord` provides the screen space coordinates and should generally be avoided to ensure shaders are consistent across backends. When targeting a Skia backend the calls to gl_FragCoord are rewritten to access local coordinates but this rewriting is not possible with Impeller. - +The value returned from `FlutterFragCoord` is distinct from `gl_FragCoord`. +`gl_FragCoord` provides the screen space coordinates and should generally be +avoided to ensure shaders are consistent across backends. When targeting a +Skia backend the calls to gl_FragCoord are rewritten to access local +coordinates but this rewriting is not possible with Impeller. #### Colors -There is no built-in data type for colors. Instead they are commonly represented as a `vec4` with each component corresponding to one of the RGBA color channels. +There is no built-in data type for colors. Instead they are commonly +represented as a `vec4` with each component corresponding to one of the RGBA +color channels. -The single output `fragColor` expects that the color value is normalized colors to be in the range of `0.0` to `1.0` and that it has premultiplied alpha. This is different than typical Flutter colors which use a `0-255` value encoding and have -unpremultipled alpha. +The single output `fragColor` expects that the color value is normalized colors +to be in the range of `0.0` to `1.0` and that it has premultiplied alpha. This +is different than typical Flutter colors which use a `0-255` value encoding and +have unpremultipled alpha. #### Samplers -A sampler provides access to a dart:ui Image object. This image can be acquired either from a decoded image or from part of the application using [Scene.toImageSync] or [Picture.toImageSync]. +A sampler provides access to a dart:ui Image object. This image can be acquired +either from a decoded image or from part of the application using +[Scene.toImageSync] or [Picture.toImageSync]. ```glsl #include @@ -162,14 +198,21 @@ void main() { } ``` -By default, the image uses a clamping address mode. Currently customization of the addressing mode is not supported and needs to be emulated in the shader. +By default, the image uses a clamping address mode. Currently customization of +the addressing mode is not supported and needs to be emulated in the shader. ### Performance Considerations -When targeting the Skia backend loading the shader may be expensive, since it must be compiled to the appropriate platform specific shader. If you intend to use one or more shaders during an animation, prefer to precache the fragment program objects before starting the animation. +When targeting the Skia backend loading the shader may be expensive, since it +must be compiled to the appropriate platform specific shader. If you intend to +use one or more shaders during an animation, prefer to precache the fragment +program objects before starting the animation. -For a more detailed guide on writing performant shaders, see https://github.com/flutter/engine/blob/main/impeller/docs/shader_optimization.md from the flutter/engine. +The FragmentShader object can be reused across frames, and this will be more +efficient than creating a new FragmentShader per-frame. +For a more detailed guide on writing performant shaders, see +[shader_optimization.md] from the flutter/engine. ### Other resources @@ -178,6 +221,7 @@ For more information, here are a few resources. * https://thebookofshaders.com/ * https://www.shadertoy.com/ +[shader_optimization.md]: https://github.com/flutter/engine/blob/main/impeller/docs/shader_optimization.md [`Canvas`]: {{site.api}}/flutter/dart-ui/Canvas-class.html [`Scene`]: {{site.api}}/flutter/dart-ui/Scene-class.html [`FragmentProgram`]: {{site.api}}/flutter/dart-ui/FragmentProgram-class.html From f08d739c5a0d6da8fa7a360490a538d780d3a364 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 5 Dec 2022 12:17:48 -0800 Subject: [PATCH 04/16] tweaks --- src/development/ui/advanced/shaders.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 219b9a6c6e3..d9285779b86 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -4,8 +4,10 @@ description: How to author and use fragment shaders. short-title: Fragment Shaders --- +{{site.alert.secondary}} Note: The HTML backend does not support the FragmentProgram API. The CanvasKit backend will support this API in a future release. +{{site.alert.end}} A shader is a program that is executed by the GPU, usually authored in a small, dart-like language such as GLSL. User authored shaders can be incorporated into @@ -103,7 +105,7 @@ A fragment program is configured by defining uniform values in the shader source and then setting these values per fragment shader instance. Uniforms are set using [FragmentShader.setFloat] or -[FragmentShader.setSampler], depending on the type of uniform. Float values +[FragmentShader.setImageSampler], depending on the type of uniform. Float values includes floats and vec2, vec3, and vec4. Sampler values are only `sampler2D`. The correct index for each uniform is determined by the order of the uniforms @@ -204,9 +206,9 @@ the addressing mode is not supported and needs to be emulated in the shader. ### Performance Considerations When targeting the Skia backend loading the shader may be expensive, since it -must be compiled to the appropriate platform specific shader. If you intend to -use one or more shaders during an animation, prefer to precache the fragment -program objects before starting the animation. +must be compiled to the appropriate platform specific shader at runtime. If you +intend to use one or more shaders during an animation, prefer to precache the +fragment program objects before starting the animation. The FragmentShader object can be reused across frames, and this will be more efficient than creating a new FragmentShader per-frame. From dd819c3763d25ce569e921c5f74db5953e2c6998 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 5 Dec 2022 15:02:16 -0800 Subject: [PATCH 05/16] ++ --- src/development/ui/advanced/shaders.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index d9285779b86..3917a6b443b 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -57,13 +57,11 @@ void updateShader(Canvas canvas, Rect rect, FragmentProgram program) { ## Canvas API -Fragment shaders can be used with most Canvas APIs that accept either solid -colors or gradients via a [Paint] object. And will cover an area determined -by the geometry of the canvas API used. For example, with a call to -[Canvas.drawRect] the shader will be evaluated for all fragments within -the rectangle. For an API like [Canvas.drawPath] with a stroked path, the -shader will be evaluated for all fragments within the stroked line. Some -APIs such as drawImage ignore the value of the shader. +Fragment shaders can be used with most Canvas APIs by setting [Paint.shader]. +For example, when using [Canvas.drawRect] the shader will be evaluated for all +fragments within the rectangle. For an API like [Canvas.drawPath] with a +stroked path, the shader will be evaluated for all fragments within the stroked +line. Some APIs such as [Canvas.drawImage] ignore the value of the shader. ```dart void paint(Canvas canvas, Size size, FragmentShader shader) { @@ -175,9 +173,9 @@ There is no built-in data type for colors. Instead they are commonly represented as a `vec4` with each component corresponding to one of the RGBA color channels. -The single output `fragColor` expects that the color value is normalized colors -to be in the range of `0.0` to `1.0` and that it has premultiplied alpha. This -is different than typical Flutter colors which use a `0-255` value encoding and +The single output `fragColor` expects that the color value is normalized to be +in the range of `0.0` to `1.0` and that it has premultiplied alpha. This is +different than typical Flutter colors which use a `0-255` value encoding and have unpremultipled alpha. #### Samplers @@ -201,7 +199,7 @@ void main() { ``` By default, the image uses a clamping address mode. Currently customization of -the addressing mode is not supported and needs to be emulated in the shader. +the address mode is not supported and needs to be emulated in the shader. ### Performance Considerations From 4d9ff4df409d3de32c2b6e64b4e1378483f1488e Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 5 Dec 2022 16:00:42 -0800 Subject: [PATCH 06/16] Update src/development/ui/advanced/shaders.md Co-authored-by: Zachary Anderson --- src/development/ui/advanced/shaders.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 3917a6b443b..40f6f8534bd 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -10,7 +10,7 @@ backend will support this API in a future release. {{site.alert.end}} A shader is a program that is executed by the GPU, usually authored in a small, -dart-like language such as GLSL. User authored shaders can be incorporated into +Dart-like language such as GLSL. User authored shaders can be incorporated into Flutter applications and packages via the FragmentProgram API. These can be used to provide rich graphical effects beyond those provided by the Flutter SDK. From e2512dced93cdb27c4ffa52d44090f16175b83a6 Mon Sep 17 00:00:00 2001 From: "Shams Zakhour (ignore Sfshaza)" <44418985+sfshaza2@users.noreply.github.com> Date: Wed, 7 Dec 2022 16:05:57 -0800 Subject: [PATCH 07/16] Update src/development/ui/advanced/shaders.md --- src/development/ui/advanced/shaders.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 40f6f8534bd..35078f1c133 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -4,9 +4,9 @@ description: How to author and use fragment shaders. short-title: Fragment Shaders --- -{{site.alert.secondary}} -Note: The HTML backend does not support the FragmentProgram API. The CanvasKit -backend will support this API in a future release. +{{site.alert.note}} + The HTML backend doesn't support the `FragmentProgram` API. + The `CanvasKit` backend will support this API in a future release. {{site.alert.end}} A shader is a program that is executed by the GPU, usually authored in a small, From a5e04a7e7ec333dbe654abcf9f7fb0129297bf6e Mon Sep 17 00:00:00 2001 From: "Shams Zakhour (ignore Sfshaza)" <44418985+sfshaza2@users.noreply.github.com> Date: Wed, 7 Dec 2022 16:06:09 -0800 Subject: [PATCH 08/16] Update src/development/ui/advanced/shaders.md --- src/development/ui/advanced/shaders.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 35078f1c133..2e046f7fdc9 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -1,5 +1,5 @@ --- -title: Writing and using Fragment Shaders +title: Writing and using fragment shaders description: How to author and use fragment shaders. short-title: Fragment Shaders --- From 7f178fb29f124a0749ece86112d5eb6b81451121 Mon Sep 17 00:00:00 2001 From: "Shams Zakhour (ignore Sfshaza)" <44418985+sfshaza2@users.noreply.github.com> Date: Wed, 7 Dec 2022 16:07:26 -0800 Subject: [PATCH 09/16] Update src/development/ui/advanced/shaders.md --- src/development/ui/advanced/shaders.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 2e046f7fdc9..8cbbe64f207 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -14,7 +14,7 @@ Dart-like language such as GLSL. User authored shaders can be incorporated into Flutter applications and packages via the FragmentProgram API. These can be used to provide rich graphical effects beyond those provided by the Flutter SDK. -## Adding Shaders to an Application +## Adding shaders to an application Shaders must be declared in the new `shaders` section of your application or package pubspec.yaml file. This allows the Flutter command line tool to compile From 6a0a1564aa3804895dbead896cbfef915c8ee169 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 8 Dec 2022 09:34:31 -0800 Subject: [PATCH 10/16] Apply suggestions from code review Co-authored-by: Shams Zakhour (ignore Sfshaza) <44418985+sfshaza2@users.noreply.github.com> --- src/development/ui/advanced/shaders.md | 118 ++++++++++++++----------- 1 file changed, 66 insertions(+), 52 deletions(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 8cbbe64f207..4df2524c41f 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -1,7 +1,7 @@ --- title: Writing and using fragment shaders description: How to author and use fragment shaders. -short-title: Fragment Shaders +short-title: Fragment shaders --- {{site.alert.note}} @@ -9,18 +9,21 @@ short-title: Fragment Shaders The `CanvasKit` backend will support this API in a future release. {{site.alert.end}} -A shader is a program that is executed by the GPU, usually authored in a small, -Dart-like language such as GLSL. User authored shaders can be incorporated into -Flutter applications and packages via the FragmentProgram API. These can be -used to provide rich graphical effects beyond those provided by the Flutter SDK. +A shader is a program executed by the GPU and usually authored in a small, +Dart-like language, such as GLSL. User-authored shaders can be added to +Flutter projects using the [`FragmentProgram`][] API. +You can use custom shaders to provide rich graphical effects beyond those +provided by the Flutter SDK. + +[`FragmentProgram`]: {{site.api}}/flutter/dart-ui/FragmentProgram-class.html ## Adding shaders to an application -Shaders must be declared in the new `shaders` section of your application or -package pubspec.yaml file. This allows the Flutter command line tool to compile -the shader to the appropriate backend format, as well as generate the necessary -runtime metadata. When running in debug mode, changes to a shader program will -trigger a recompilation and update of the shader during hot reload or hot +Shaders must be declared in the `shaders` section of your project's `pubspec.yaml` file. +The Flutter command-line tool to compiles the shader to its appropriate backend format, +as well as generates the necessary runtime metadata. +When running in debug mode, changes to a shader program +triggers recompilation and updates the shader during hot reload or hot restart. ```yaml @@ -29,13 +32,14 @@ flutter: - shaders/myshader.frag ``` -Shaders from packages can be included using the same technique as other assets. +Shaders from packages are added to a project using the same technique as other assets. #### Loading shaders at runtime -FragmentPrograms can be loaded at runtime using the [FragmentProgram.fromAsset] -constructor. The key should be the file path specified in the pubspec.yaml -above. +Load a `FragmentProgram` at runtime using the [`FragmentProgram.fromAsset`][] +constructor. Specify the path to the shader in the `pubspec.yaml` file, as shown above. + +[`FragmentProgram.fromAsset`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentProgram/fromAsset.html ```dart void loadMyShader() async { @@ -57,11 +61,17 @@ void updateShader(Canvas canvas, Rect rect, FragmentProgram program) { ## Canvas API -Fragment shaders can be used with most Canvas APIs by setting [Paint.shader]. -For example, when using [Canvas.drawRect] the shader will be evaluated for all -fragments within the rectangle. For an API like [Canvas.drawPath] with a -stroked path, the shader will be evaluated for all fragments within the stroked -line. Some APIs such as [Canvas.drawImage] ignore the value of the shader. +Fragment shaders can be used with most Canvas APIs by setting [`Paint.shader`][]. +For example, when using [`Canvas.drawRect`][] the shader is evaluated for all +fragments within the rectangle. For an API like [`Canvas.drawPath`][] with a +stroked path, the shader is evaluated for all fragments within the stroked +line. Some APIs, such as [`Canvas.drawImage`][], ignore the value of the shader. + +[`Canvas.drawImage`]: {{site.api}}/flutter/dart-ui/Canvas/drawImage.html +[`Canvas.drawRect`]: {{site.api}}/flutter/dart-ui/Canvas/drawRect.html +[`Canvas.drawPath`]: {{site.api}}/flutter/dart-ui/Canvas/drawPath.html +[`Paint.shader`]: {{site.api}}/flutter/dart-ui/Paint/shader.html + ```dart void paint(Canvas canvas, Size size, FragmentShader shader) { @@ -83,11 +93,12 @@ void paint(Canvas canvas, Size size, FragmentShader shader) { ``` -## Authoring Shaders +## Authoring shaders -Shaders are authored as GLSL source files. Any version from 460 down to 100 -is supported, though some available features are restricted. For the rest -of the examples in this document `460 core` will be used. +Shaders are authored as GLSL source files. +Any GLSL version from 460 down to 100 is supported, +though some available features are restricted. +The rest of the examples in this document use version `460 core`. * UBOs and SSBOs are unsupported. * `sampler2D` is the only supported sampler type @@ -99,17 +110,17 @@ of the examples in this document `460 core` will be used. #### Uniforms -A fragment program is configured by defining uniform values in the shader -source and then setting these values per fragment shader instance. +Configure a fragment program by defining `uniform` values in the GLSL shader +source and then setting these values in Dart for each fragment shader instance. Uniforms are set using [FragmentShader.setFloat] or [FragmentShader.setImageSampler], depending on the type of uniform. Float values includes floats and vec2, vec3, and vec4. Sampler values are only `sampler2D`. -The correct index for each uniform is determined by the order of the uniforms -as defined in the fragment program. For data types that are composed of -multiple floats such as a vec4, more than one call to [FragmentShader.setFloat] -is required. +The correct index for each `uniform` value is determined by the order that the uniform values +are defined in the fragment program. For data types composed of +multiple floats, such as a `vec4`, you must call [`FragmentShader.setFloat`][] +once for each value. For example, given the following uniforms in a fragment program: @@ -120,7 +131,8 @@ uniform vec2 uMagnitude; uniform vec4 uColor; ``` -The corresponding Dart code to correctly initialize these uniforms is: +The corresponding Dart code to initialize these `uniform` values is +as follows: ```dart void updateShader(FragmentShader shader, Color color, Image image) { @@ -134,7 +146,7 @@ void updateShader(FragmentShader shader, Color color, Image image) { shader.setFloat(5, color.blue / 255 * color.opacity); // uColor b shader.setFloat(6, color.opacity); // uColor a - // initialize sampler uniform. + // Initialize sampler uniform. shader.setImageSampler(0, image); } ``` @@ -145,7 +157,7 @@ index starting over at 0. Any float uniforms that are left uninitialized will default to `0`. -#### Current Position +#### Current position The shader has access to a varying which contains the local coordinates for the particular fragment that is being evaluated. This can be used to compute @@ -163,13 +175,13 @@ void main() { The value returned from `FlutterFragCoord` is distinct from `gl_FragCoord`. `gl_FragCoord` provides the screen space coordinates and should generally be -avoided to ensure shaders are consistent across backends. When targeting a -Skia backend the calls to gl_FragCoord are rewritten to access local -coordinates but this rewriting is not possible with Impeller. +avoided to ensure that shaders are consistent across backends. When targeting a +Skia backend, the calls to `gl_FragCoord` are rewritten to access local +coordinates but this rewriting isn't possible with Impeller. #### Colors -There is no built-in data type for colors. Instead they are commonly +There isn't a built-in data type for colors. Instead they are commonly represented as a `vec4` with each component corresponding to one of the RGBA color channels. @@ -180,9 +192,13 @@ have unpremultipled alpha. #### Samplers -A sampler provides access to a dart:ui Image object. This image can be acquired -either from a decoded image or from part of the application using -[Scene.toImageSync] or [Picture.toImageSync]. +A sampler provides access to a `dart:ui` `Image` object. +This image can be acquired either from a decoded image +or from part of the application using +[`Scene.toImageSync`][] or [`Picture.toImageSync`][]. + +[Picture.toImageSync`]: https://master-api.flutter.dev/flutter/dart-ui/Picture/toImageSync.html +[`Scene.toImageSync`]: https://master-api.flutter.dev/flutter/dart-ui/Scene/toImageSync.html ```glsl #include @@ -201,15 +217,15 @@ void main() { By default, the image uses a clamping address mode. Currently customization of the address mode is not supported and needs to be emulated in the shader. -### Performance Considerations +### Performance considerations -When targeting the Skia backend loading the shader may be expensive, since it -must be compiled to the appropriate platform specific shader at runtime. If you -intend to use one or more shaders during an animation, prefer to precache the +When targeting the Skia backend, loading the shader might be expensive since it +must be compiled to the appropriate platform-specific shader at runtime. If you +intend to use one or more shaders during an animation, consider precaching the fragment program objects before starting the animation. -The FragmentShader object can be reused across frames, and this will be more -efficient than creating a new FragmentShader per-frame. +You can reuse a `FragmentShader` object across frames; +this is more efficient than creating a new `FragmentShader` for each frame. For a more detailed guide on writing performant shaders, see [shader_optimization.md] from the flutter/engine. @@ -218,11 +234,9 @@ For a more detailed guide on writing performant shaders, see For more information, here are a few resources. -* https://thebookofshaders.com/ -* https://www.shadertoy.com/ +* [The Book of Shaders][] by Patricio Gonzalez Vivo and Jen Lowe +* [Shader toy][], a collaborative shader playground + +[Shader toy]: https://www.shadertoy.com/ +[The Book of Shaders]: https://thebookofshaders.com/ -[shader_optimization.md]: https://github.com/flutter/engine/blob/main/impeller/docs/shader_optimization.md -[`Canvas`]: {{site.api}}/flutter/dart-ui/Canvas-class.html -[`Scene`]: {{site.api}}/flutter/dart-ui/Scene-class.html -[`FragmentProgram`]: {{site.api}}/flutter/dart-ui/FragmentProgram-class.html -[`FragmentShader`]: {{site.api}}/flutter/dart-ui/FragmentShader-class.html From d4a20acd8648dc6736d0b8cb4c1653a81bd9958a Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 8 Dec 2022 09:55:49 -0800 Subject: [PATCH 11/16] more adjustments --- src/_data/sidenav.yml | 2 ++ src/development/ui/advanced/shaders.md | 38 ++++++++++++++++---------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/_data/sidenav.yml b/src/_data/sidenav.yml index 749eba6f8fe..00c96b40037 100644 --- a/src/_data/sidenav.yml +++ b/src/_data/sidenav.yml @@ -110,6 +110,8 @@ permalink: /development/ui/advanced/focus - title: Gestures permalink: /development/ui/advanced/gestures + - title: Shaders + permalink: /development/ui/advanced/shaders - title: Slivers permalink: /development/ui/advanced/slivers - title: Splash screens diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 4df2524c41f..ab4ce1fd21a 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -11,7 +11,7 @@ short-title: Fragment shaders A shader is a program executed by the GPU and usually authored in a small, Dart-like language, such as GLSL. User-authored shaders can be added to -Flutter projects using the [`FragmentProgram`][] API. +Flutter projects using the [`FragmentProgram`][] API. You can use custom shaders to provide rich graphical effects beyond those provided by the Flutter SDK. @@ -48,8 +48,8 @@ void loadMyShader() async { ``` The FragmentProgram object can be used to create one or more FragmentShader -instances. A FragmentShader represents a particular combination of a -program and bound uniforms. +instances. A FragmentShader object represents a fragment program along with +a particular set of uniforms. ```dart void updateShader(Canvas canvas, Rect rect, FragmentProgram program) { @@ -100,29 +100,34 @@ Any GLSL version from 460 down to 100 is supported, though some available features are restricted. The rest of the examples in this document use version `460 core`. -* UBOs and SSBOs are unsupported. +Also note the following special cases: + +* UBOs and SSBOs aren't supported * `sampler2D` is the only supported sampler type -* Only the two argument version of `texture` (sampler and uv) is supported. -* No varyings may be declared. - * Note: A position varying is available for each shader -* All precision hints are ignored when targeting Skia. -* Unsigned integers and booleans are unsupported. +* Only the two-argument version of `texture` (sampler and uv) is supported +* No additional varying inputs may be declared +* All precision hints are ignored when targeting Skia +* Unsigned integers and booleans aren't supported #### Uniforms Configure a fragment program by defining `uniform` values in the GLSL shader source and then setting these values in Dart for each fragment shader instance. -Uniforms are set using [FragmentShader.setFloat] or -[FragmentShader.setImageSampler], depending on the type of uniform. Float values -includes floats and vec2, vec3, and vec4. Sampler values are only `sampler2D`. +Set the `uniform` value using the [`FragmentShader.setFloat`][] or +[`FragmentShader.setImageSampler`][] methods, depending on the _type_˜ of uniform value. +In GLSL, floating point values includes `float`, `vec2`, `vec3`, and `vec4` types. +A GLSL sampler value is a `sampler2D` type. + +[FragmentShader.setFloat`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentShader/setFloat.html +[`FragmentShader.setImageSampler`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentShader/setImageSampler.html The correct index for each `uniform` value is determined by the order that the uniform values are defined in the fragment program. For data types composed of multiple floats, such as a `vec4`, you must call [`FragmentShader.setFloat`][] once for each value. -For example, given the following uniforms in a fragment program: +For example, given the following uniforms declarations in a GLSL fragment program: ```glsl uniform float uScale; @@ -214,8 +219,11 @@ void main() { } ``` -By default, the image uses a clamping address mode. Currently customization of -the address mode is not supported and needs to be emulated in the shader. +By default, the image uses [`TileMode.clamp`][] to determine how values outside +of the range of `[0, 1]` behave. Customization of the tile mode is not +supported and needs to be emulated in the shader. + +[`TileMode.clamp`]: https://master-api.flutter.dev/flutter/dart-ui/TileMode.html ### Performance considerations From 6d85928f1b64ceef862be661f9e7c81b8ca6fce9 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 8 Dec 2022 09:57:18 -0800 Subject: [PATCH 12/16] Apply suggestions from code review Co-authored-by: Shams Zakhour (ignore Sfshaza) <44418985+sfshaza2@users.noreply.github.com> --- src/development/ui/advanced/shaders.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index ab4ce1fd21a..8a60203aa22 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -156,19 +156,20 @@ void updateShader(FragmentShader shader, Color color, Image image) { } ``` -Note how the indexes used does not count the `sampler2D` uniform. This uniform -will be set separately with [FragmentShader.setImageSampler], with the -index starting over at 0. +Note that the `setFloat` method isn't called on the `sampler2D` uniform value, +so it doesn't appear in its index. Set the index of any `shader2D` values +separately with [`FragmentShader.setImageSampler`[]] +and start the index over at 0. Any float uniforms that are left uninitialized will default to `0`. #### Current position -The shader has access to a varying which contains the local coordinates for -the particular fragment that is being evaluated. This can be used to compute -effects that depend on the position. This position can be accessed by +The shader has access to a `varying` value that contains the local coordinates for +the particular fragment being evaluated. Use this feature to compute +effects that depend on the current position, which can be accessed by importing the `flutter/runtime_effect.glsl` library and calling the -`FlutterFragCoord` function like below. +`FlutterFragCoord` function . For example: ```glsl #include @@ -235,8 +236,11 @@ fragment program objects before starting the animation. You can reuse a `FragmentShader` object across frames; this is more efficient than creating a new `FragmentShader` for each frame. -For a more detailed guide on writing performant shaders, see -[shader_optimization.md] from the flutter/engine. +For a more detailed guide on writing performant shaders, +check out [Writing efficient shaders][] on GitHub. + +[Shader compilation jank]: {{site.url}}/perf/shader +[Writing efficient shaders]: {{site.github}}/flutter/engine/blob/main/impeller/docs/shader_optimization.md) ### Other resources From 37fff4b71efbdb524ca18c94ab2970183a349c68 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 8 Dec 2022 10:10:56 -0800 Subject: [PATCH 13/16] ++ --- src/development/ui/advanced/shaders.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 8a60203aa22..66c4af8c96f 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -119,14 +119,14 @@ Set the `uniform` value using the [`FragmentShader.setFloat`][] or In GLSL, floating point values includes `float`, `vec2`, `vec3`, and `vec4` types. A GLSL sampler value is a `sampler2D` type. -[FragmentShader.setFloat`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentShader/setFloat.html -[`FragmentShader.setImageSampler`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentShader/setImageSampler.html - The correct index for each `uniform` value is determined by the order that the uniform values are defined in the fragment program. For data types composed of multiple floats, such as a `vec4`, you must call [`FragmentShader.setFloat`][] once for each value. +[FragmentShader.setFloat`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentShader/setFloat.html +[`FragmentShader.setImageSampler`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentShader/setImageSampler.html + For example, given the following uniforms declarations in a GLSL fragment program: ```glsl @@ -156,10 +156,9 @@ void updateShader(FragmentShader shader, Color color, Image image) { } ``` -Note that the `setFloat` method isn't called on the `sampler2D` uniform value, -so it doesn't appear in its index. Set the index of any `shader2D` values -separately with [`FragmentShader.setImageSampler`[]] -and start the index over at 0. +Note how the indexes used does not count the `sampler2D` uniform. This uniform +will be set separately with [`FragmentShader.setImageSampler`][], with the +index starting over at 0. Any float uniforms that are left uninitialized will default to `0`. From c8dce30318be02c08cfc67f8ebb2808a918bd0ae Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 8 Dec 2022 10:23:26 -0800 Subject: [PATCH 14/16] ++ --- src/development/ui/advanced/shaders.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 66c4af8c96f..719ef30353e 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -124,7 +124,7 @@ are defined in the fragment program. For data types composed of multiple floats, such as a `vec4`, you must call [`FragmentShader.setFloat`][] once for each value. -[FragmentShader.setFloat`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentShader/setFloat.html +[`FragmentShader.setFloat`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentShader/setFloat.html [`FragmentShader.setImageSampler`]: https://master-api.flutter.dev/flutter/dart-ui/FragmentShader/setImageSampler.html For example, given the following uniforms declarations in a GLSL fragment program: @@ -202,7 +202,7 @@ This image can be acquired either from a decoded image or from part of the application using [`Scene.toImageSync`][] or [`Picture.toImageSync`][]. -[Picture.toImageSync`]: https://master-api.flutter.dev/flutter/dart-ui/Picture/toImageSync.html +[`Picture.toImageSync`]: https://master-api.flutter.dev/flutter/dart-ui/Picture/toImageSync.html [`Scene.toImageSync`]: https://master-api.flutter.dev/flutter/dart-ui/Scene/toImageSync.html ```glsl From 1702a819d15ef2f6d1cca0effd7b89e60a9b11b3 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Sun, 11 Dec 2022 12:26:48 -0800 Subject: [PATCH 15/16] Update src/development/ui/advanced/shaders.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Loïc Sharma <737941+loic-sharma@users.noreply.github.com> --- src/development/ui/advanced/shaders.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 719ef30353e..7b5a1a2a4ea 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -20,7 +20,7 @@ provided by the Flutter SDK. ## Adding shaders to an application Shaders must be declared in the `shaders` section of your project's `pubspec.yaml` file. -The Flutter command-line tool to compiles the shader to its appropriate backend format, +The Flutter command-line tool compiles the shader to its appropriate backend format, as well as generates the necessary runtime metadata. When running in debug mode, changes to a shader program triggers recompilation and updates the shader during hot reload or hot From b8df2eed5fbc8c935ef0ff01574c79e1ef9e338d Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Tue, 13 Dec 2022 13:46:25 -0800 Subject: [PATCH 16/16] Update src/development/ui/advanced/shaders.md Co-authored-by: Shams Zakhour (ignore Sfshaza) <44418985+sfshaza2@users.noreply.github.com> --- src/development/ui/advanced/shaders.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/development/ui/advanced/shaders.md b/src/development/ui/advanced/shaders.md index 7b5a1a2a4ea..74dab667ed5 100644 --- a/src/development/ui/advanced/shaders.md +++ b/src/development/ui/advanced/shaders.md @@ -1,6 +1,6 @@ --- title: Writing and using fragment shaders -description: How to author and use fragment shaders. +description: How to author and use fragment shaders to create custom visual effects in your Flutter app. short-title: Fragment shaders ---