shader 1.0.0 copy "shader: ^1.0.0" to clipboard
shader: ^1.0.0 copied to clipboard

Command-line application for compiling GLSL shaders into Flutter-compatible SPR-V byte code.

shader #

Shader manages the compilation of your GLSL shaders into SPIR-V byte code and Dart code.

Quickstart

# Install cli
dart pub global activate shader

# Compile all glsl files in our project
shader --use-remote --to-dart

# Discover all features
shader --help

Table of Contents #

Getting started

Usage

Writing shaders

Getting started #

Install the command-line executable shader for your current user:

dart pub global activate shader

Now you can use the shader CLI tool:

shader --help

Hint: If pub binaries are not known to the path, you can also run it by:

dart pub global run shader --help

Usage #

Compile to Dart #

The easiest way of using shaders in your app, is to use it this way:

shader --use-remote --to-dart

It will scan your project for *.glsl files and use the hosted cloud service to compile it. Flutter needs SPR-V byte code at runtime.

A very simple shader red-shader.glsl could be this:

#version 320 es

precision highp float;

layout(location = 0) out vec4 fragColor;

void main() {
    fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

This shader has no uniforms (input parameters) and paints each pixel red.

The compiler created a dart file red_shader_sprv.dart that contains a function Future<FragmentProgram> redShaderFragmentProgram() that will initialize the shader at runtime.

We can utilize a FutureBuilder to load that:

import 'dart:ui';
import 'package:flutter/material.dart';

/// Import file generated by cli
import 'package:flutter_app/shader/red_shader_sprv.dart';

class RedShaderWidget extends StatelessWidget {
  const RedShaderWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<FragmentProgram>(
      /// Use the generated loader function here
      future: redShaderFragmentProgram(),
      builder: ((context, snapshot) {
        if (!snapshot.hasData) {
          /// Shader is loading
          return const WidgetWhenLoading();
        }

        /// Shader is ready to use
        return WidgetThatUsesShader(snapshot.data!);
      }),
    );
  }
}

You can find an app example of Red Shader.

Use of uniforms #

Uniforms is the term in the GLSL world for input parameter. The uniforms can be changed for each frame, but they are constant for every pixel during a single frame.

Given the following GLSL file:

#version 320 es

precision highp float;

layout(location = 0) out vec4 fragColor;

// define uniforms:
layout(location = 0) uniform vec3 color1;
layout(location = 1) uniform vec3 color2;
layout(location = 2) uniform vec3 someValue;
layout(location = 3) uniform vec2 size;

void main() {
    // ...
}

This can be addressed in FragmentProgram's shader() method:

@override
void paint(Canvas canvas, Size size) {
  /// Inputs
  Color color1 = Colors.blue;
  Color color2 = Colors.green;
  double someValue = 0.5;

  /// Create paint using a shader
  final paint = Paint()
    ..shader = fragmentProgram.shader(

        /// Specify input parameter (uniforms)
        floatUniforms: Float32List.fromList([
      /// color1 takes 3 floats and will be mapped to `vec3`
      color1.red / 255.0,
      color1.green / 255.0,
      color1.blue / 255.0,

      /// color2 also takes 3 floats and will be mapped to `vec3`
      color2.red / 255.0,
      color2.green / 255.0,
      color2.blue / 255.0,

      /// someValue takes 1 float and will be mapped to `float`
      someValue,

      /// size takes 2 floats and will be mapped to `vec2`
      size.width,
      size.height,
    ]));

  /// Draw a rectangle with the shader-paint
  canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);
}

Also take a look at Color Shader example, that combines Flutter animtions and the use of uniforms.

Make use of sampler uniform #

Image textures can be accessed via sampler2d uniforms:

layout(location = 0) uniform sampler2D image;

For that you need to create an ImageShader:

final asset = await rootBundle.load("assets/image.jpg");
final image = await decodeImageFromList(asset.buffer.asUint8List());

/// Create ImageShader that will provide a GLSL sampler
final ImageShader imageShader = ImageShader(
  image,
  // Specify how image repetition is handled for x and y dimension
  TileMode.repeated,
  TileMode.repeated,
  // Transformation matrix (identity matrix = no transformation)
  Matrix4.identity().storage,
);

That ImageShader can be passed into the FragmentProgram's shader() method as samplerUniform:

final paint = Paint()
  ..shader = fragmentProgram.shader(
    samplerUniforms: [
      imageShader,
    ],
  );

You can see everything wired up in the Image Scale app example.

Use a local compiler #

If you don't want to rely on the hosted cloud service or the cloud service not available, you can use local compiler.

You can download the compiler at https://github.com/google/shaderc.

The --use-local option takes a path that roughly points to the compiler binary:

shader --use-local $HOME/sdk/shaderc --to-dart

Improve development cycle #

In order to iterate faster and use the hot-reload, you can use the --watch flag:

shader --use-remote --to-dart --watch

shader --use-local $HOME/sdk/shaderc --to-dart --watch

Other features #

The shader executable also supports some other options and output format. Type to find get information:

shader --help

Writing shaders #

This section covers useful information and resources writing own shader code.

Constraints in Flutter #

Shaders are not supported for Flutter web, yet. But there is a project plan for the Flutter engine developers to enable it.

Also the capabilities of GLSL language feature are restricted. Take a look at the specifications of the SPIR-V Transpiler.

This package compiles GLSL code to SPIR-V code, and at runtime SPIR-V transpiler converts it to native API (e.g. OpenGL, Vulkan). So it might be that shader will compile fine, but it fails at runtime.

Learning GLSL #

There are various sources to learn GLSL:

61
likes
140
pub points
55%
popularity

Publisher

verified publisherfelix-blaschke.de

Command-line application for compiling GLSL shaders into Flutter-compatible SPR-V byte code.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

args, http, path, stringr, watcher

More

Packages that depend on shader