shader_buffers 1.0.1 copy "shader_buffers: ^1.0.1" to clipboard
shader_buffers: ^1.0.1 copied to clipboard

Using shaders to feed a shader. Make shaders simplier to use.

example/lib/main.dart

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

typedef Layers = ({LayerBuffer mainImage, List<LayerBuffer> buffers});

void main() {
  runApp(const MainApp());
}

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> with WidgetsBindingObserver {
  late Layers shader;
  ValueNotifier<bool> operations = ValueNotifier<bool>(false);
  ShaderController controller = ShaderController();
  ValueNotifier<List<Uniform>> uniform = ValueNotifier([]);

  @override
  void initState() {
    super.initState();
    shader = shader7();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      themeMode: ThemeMode.dark,
      darkTheme: ThemeData.dark(useMaterial3: true),
      theme: ThemeData(scaffoldBackgroundColor: Colors.black),
      home: Scaffold(
        body: Padding(
          padding: const EdgeInsets.all(16),
          child: Stack(
            alignment: Alignment.center,
            children: [
              ShaderBuffers(
                key: UniqueKey(),
                controller: controller,
                // width: 250,
                // height: 300,
                mainImage: shader.mainImage,
                buffers: shader.buffers,
              ),
              Align(
                alignment: Alignment.bottomCenter,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    ...List.generate(uniform.value.length, (index) {
                      return ValueListenableBuilder(
                        valueListenable: uniform,
                        builder: (_, v, __) {
                          return Row(
                            children: [
                              /// Sliders to control the uniforms
                              Expanded(
                                child: Slider(
                                  value: v[index].value,
                                  min: uniform.value[index].range.start,
                                  max: uniform.value[index].range.end,
                                  onChanged: (value) {
                                    uniform.value[index].value = value;
                                    uniform.value = uniform.value.toList();
                                  },
                                ),
                              ),

                              /// Button to animate the uniform
                              IconButton(
                                onPressed: () {
                                  controller.animateUniform(
                                    uniformName: uniform.value[index].name,
                                    begin: uniform.value[index].range.start,
                                    end: uniform.value[index].range.end,
                                    onAnimationEnded: (ctrl, uniformValue) {
                                      /// Just update sliders
                                      uniform.value = uniform.value.toList();
                                    },
                                  );
                                },
                                icon: const Icon(Icons.animation),
                              ),
                            ],
                          );
                        },
                      );
                    }),
                    Wrap(
                      alignment: WrapAlignment.center,
                      spacing: 4,
                      runSpacing: 4,
                      children: [
                        ElevatedButton(
                          onPressed: () {
                            setState(() {
                              shader = shader1();
                            });
                          },
                          child: const Text('1'),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            setState(() {
                              shader = shader2();
                            });
                          },
                          child: const Text('2'),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            setState(() {
                              shader = shader3();
                            });
                          },
                          child: const Text('3'),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            setState(() {
                              shader = shader4();
                            });
                          },
                          child: const Text('4'),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            setState(() {
                              shader = shader5();
                            });
                          },
                          child: const Text('5'),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            setState(() {
                              shader = shader6();
                            });
                          },
                          child: const Text('6'),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            setState(() {
                              shader = shader7();
                            });
                          },
                          child: const Text('7'),
                        ),
                      ],
                    ),
                    const SizedBox(height: 4),
                    Wrap(
                      alignment: WrapAlignment.center,
                      spacing: 4,
                      runSpacing: 4,
                      children: [
                        ElevatedButton(
                          onPressed: controller.pause,
                          child: const Text('pause'),
                        ),
                        ElevatedButton(
                          onPressed: controller.play,
                          child: const Text('play'),
                        ),
                        ElevatedButton(
                          onPressed: controller.rewind,
                          child: const Text('rewind'),
                        ),
                        StatefulBuilder(
                          builder: (context, setState) {
                            final s = controller.getState();
                            return ElevatedButton(
                              onPressed: () => setState(() {}),
                              child: Text('state: ${s.name}\npress to refresh'),
                            );
                          },
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Layers shader1() {
    uniform.value = [];
    final mainLayer = LayerBuffer(
      shaderAssetsName: 'assets/shaders/page_curl.frag',
      // floatUniforms: [1.0],
    )..setChannels(
        [
          // IChannel(assetsTexturePath: 'assets/flutter.png'),
          // IChannel(assetsTexturePath: 'assets/bricks.jpg'),
          IChannel(child: const Widget1()),
          IChannel(child: const Widget2()),
        ],
      );

    /// add checks to see when the pointer is near the left edge
    controller = ShaderController();
    controller.addConditionalOperation(
      (
        layerBuffer: mainLayer,
        param: Param(CommonUniform.iMouseXNormalized),
        checkType: CheckOperator.minor,
        checkValue: 0.2,
        operation: (ctrl, result) {
          if (result) {
            ctrl
              ..swapChannels(mainLayer, 0, 1)
              ..pause()
              ..rewind();
          }
        },
      ),
    );
    return (mainImage: mainLayer, buffers: []);
  }

  Layers shader2() {
    uniform.value = [
      Uniform(
        name: 'a',
        range: const RangeValues(0, 10),
        defaultValue: 1,
        value: 1,
      ),
      Uniform(
        name: 'b',
        range: const RangeValues(0, 10),
        defaultValue: 1,
        value: 1,
      ),
      Uniform(
        name: 'c',
        range: const RangeValues(0, 10),
        defaultValue: 1,
        value: 1,
      ),
    ];

    final mainLayer = LayerBuffer(
      shaderAssetsName: 'assets/shaders/water.frag',
      uniforms: Uniforms(uniform.value),
    )..setChannels(
        [
          IChannel(assetsTexturePath: 'assets/flutter.png'),
          // IChannel(child: const Widget1()),
        ],
      );

    return (mainImage: mainLayer, buffers: []);
  }

  Layers shader3() {
    uniform.value = [];
    final mainLayer = LayerBuffer(
      shaderAssetsName: 'assets/shaders/page_curl.frag',
      // floatUniforms: [0.1],
    );

    // ignore: cascade_invocations
    mainLayer.setChannels(
      [
        IChannel(assetsTexturePath: 'assets/flutter.png'),
        IChannel(assetsTexturePath: 'assets/bricks.jpg'),
        // IChannel(child: const Widget1()),
        // IChannel(child: const Widget2()),
      ],
    );
    return (mainImage: mainLayer, buffers: []);
  }

  Layers shader4() {
    uniform.value = [
      Uniform(
        name: 'R',
        range: const RangeValues(0, 1),
        defaultValue: 0.9,
        value: 0.9,
      ),
      Uniform(
        name: 'G',
        range: const RangeValues(0, 1),
        defaultValue: 0.9,
        value: 0.9,
      ),
      Uniform(
        name: 'B',
        range: const RangeValues(0, 1),
        defaultValue: 0.2,
        value: 0.2,
      ),
    ];

    final mainLayer = LayerBuffer(
      shaderAssetsName: 'assets/shaders/test_isself_main.frag',
    );

    final bufferA = LayerBuffer(
      shaderAssetsName: 'assets/shaders/test_isself_buffer_a.frag',
      uniforms: Uniforms(uniform.value),
    );

    mainLayer.setChannels([IChannel(buffer: bufferA)]);

    /// add checks to see when R>0.5
    controller = ShaderController();
    controller.addConditionalOperation(
      (
        layerBuffer: bufferA,
        param: Param(CommonUniform.customUniform, uniformId: 0),
        checkType: CheckOperator.major,
        checkValue: 0.5,
        operation: (ctrl, result) {
          // debugPrint('$result  ${bufferA.uniforms!.uniforms[0].value}');
        },
      ),
    );

    return (mainImage: mainLayer, buffers: [bufferA]);
  }

  Layers shader5() {
    uniform.value = [];
    final bufferA = LayerBuffer(
      shaderAssetsName: 'assets/shaders/shader1_bufferA.frag',
    );

    final mainLayer = LayerBuffer(
      shaderAssetsName: 'assets/shaders/shader1_main.frag',
    );

    bufferA.setChannels([IChannel(buffer: bufferA)]);
    mainLayer.setChannels([IChannel(buffer: bufferA)]);
    return (mainImage: mainLayer, buffers: [bufferA]);
  }

  Layers shader6() {
    uniform.value = [];

    final mainLayer = LayerBuffer(
      shaderAssetsName: 'assets/shaders/mouse2.frag',
    );
    return (mainImage: mainLayer, buffers: []);
  }

  Layers shader7() {
    uniform.value = [];
    final bufferA = LayerBuffer(
      shaderAssetsName: 'assets/shaders/shader2_bufferA.frag',
    );

    final mainLayer = LayerBuffer(
      shaderAssetsName: 'assets/shaders/shader2_main.frag',
    );

    bufferA.setChannels([IChannel(buffer: bufferA)]);
    mainLayer.setChannels([IChannel(buffer: bufferA)]);
    return (mainImage: mainLayer, buffers: [bufferA]);
  }
}

class Widget1 extends StatelessWidget {
  const Widget1({super.key});

  @override
  Widget build(BuildContext context) {
    return Card(
      color: Colors.green[100],
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            const Icon(Icons.account_circle, size: 42),
            const SizedBox(width: 16),
            const Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  'Widget 1',
                  style: TextStyle(
                    color: Colors.black,
                    fontWeight: FontWeight.w900,
                  ),
                ),
                Text(
                  'shader_preset',
                  style: TextStyle(color: Colors.black),
                ),
              ],
            ),
            const Spacer(),
            ElevatedButton(
              onPressed: () {
                print('Widget 1');
              },
              child: const Text('Widget 1'),
            ),
            const Icon(Icons.add_box_rounded, size: 42),
          ],
        ),
      ),
    );
  }
}

class Widget2 extends StatelessWidget {
  const Widget2({super.key});

  @override
  Widget build(BuildContext context) {
    return Card(
      color: Colors.yellow[100],
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            const Icon(Icons.ac_unit, color: Colors.red, size: 42),
            const SizedBox(width: 16),
            const Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  'Widget 2',
                  style: TextStyle(
                    color: Colors.black,
                    fontWeight: FontWeight.w900,
                  ),
                ),
                Text(
                  'shader_preset',
                  style: TextStyle(color: Colors.black),
                ),
              ],
            ),
            const Spacer(),
            ElevatedButton(
              onPressed: () {
                print('Widget 2');
              },
              child: const Text('Widget 2'),
            ),
            const Spacer(),
            const Icon(Icons.delete_forever, color: Colors.red, size: 42),
          ],
        ),
      ),
    );
  }
}
35
likes
140
pub points
55%
popularity

Publisher

verified publishermarcobavagnoli.com

Using shaders to feed a shader. Make shaders simplier to use.

Repository (GitHub)
View/report issues

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

flutter

More

Packages that depend on shader_buffers