shady 2.2.0
shady: ^2.2.0 copied to clipboard
Making it easier to work with GLSL shaders in Flutter.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:shady/shady.dart';
final shaderToyShaders = [
Shady(assetName: 'assets/shaders/st3.frag', shaderToy: true),
Shady(assetName: 'assets/shaders/st0.frag', shaderToy: true),
Shady(assetName: 'assets/shaders/st2.frag', shaderToy: true),
Shady(assetName: 'assets/shaders/st4.frag', shaderToy: true),
Shady(assetName: 'assets/shaders/st6.frag', shaderToy: true),
Shady(assetName: 'assets/shaders/st7.frag', shaderToy: true),
Shady(assetName: 'assets/shaders/st8.frag', shaderToy: true),
Shady(assetName: 'assets/shaders/st9.frag', shaderToy: true),
Shady(assetName: 'assets/shaders/st5.frag', shaderToy: true),
Shady(assetName: 'assets/shaders/st1.frag', shaderToy: true),
];
final imageShaders = [
// Image shaders
Shady(
assetName: 'assets/shaders/img0.frag',
uniforms: [
UniformFloat(
key: 'time',
transformer: UniformFloat.secondsPassed,
),
UniformVec3(
key: 'resolution',
transformer: UniformVec3.resolution,
),
],
samplers: [
TextureSampler(
key: 'cat',
asset: 'assets/textures/cat.png',
),
],
),
];
final interactiveShaders = [
Shady(
assetName: 'assets/shaders/it0.frag',
uniforms: [
UniformFloat(key: 'time', transformer: UniformFloat.secondsPassed),
UniformVec3(key: 'resolution', transformer: UniformVec3.resolution),
UniformVec2(key: 'inputCoord'),
UniformFloat(key: 'intensity', initialValue: 0.5)
],
),
Shady(
assetName: 'assets/shaders/it1.frag',
uniforms: [
UniformFloat(key: 'time', transformer: UniformFloat.secondsPassed),
UniformVec3(key: 'resolution', transformer: UniformVec3.resolution),
UniformVec2(key: 'inputCoord'),
UniformFloat(key: 'intensity', initialValue: 0.5)
],
),
];
class GalleryPage extends StatefulWidget {
final String title;
final List<Shady> shadys;
final Widget Function(BuildContext context, Shady shady) shadyBuilder;
const GalleryPage({
required this.title,
required this.shadyBuilder,
required this.shadys,
super.key,
});
@override
State<GalleryPage> createState() => _GalleryPageState();
}
class _GalleryPageState extends State<GalleryPage> {
var _index = 0;
var _tickerEnabled = true;
void _nextShader() {
setState(() => _index = (_index + 1) % widget.shadys.length);
}
void toggleTickerMode() {
setState(() => _tickerEnabled = !_tickerEnabled);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
actions: [
IconButton(
icon: Icon(_tickerEnabled ? Icons.pause : Icons.play_arrow),
onPressed: toggleTickerMode,
),
],
),
body: TickerMode(
enabled: _tickerEnabled,
child: Builder(builder: (context) {
return Stack(
children: [
Positioned.fill(
child: widget.shadyBuilder(
context,
widget.shadys[_index],
),
),
Positioned(
bottom: 20,
left: 10,
right: 10,
child: Padding(
padding: const EdgeInsets.all(8),
child: Row(
children: [
Slider(
min: -2,
max: 3,
value: widget.shadys[_index].timeMod,
onChanged: (v) => setState(() => widget.shadys[_index].timeMod = v),
),
ElevatedButton(
onPressed: _nextShader,
child: const Text('Next'),
),
],
),
),
),
],
);
}),
),
key: ValueKey(widget.shadys[_index]),
);
}
}
class PageButton extends StatelessWidget {
final String title;
final Widget Function(BuildContext context, Shady shady) shadyBuilder;
final List<Shady> shadys;
const PageButton({
required this.title,
required this.shadyBuilder,
required this.shadys,
super.key,
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
child: Text(title),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => GalleryPage(
title: title,
shadyBuilder: shadyBuilder,
shadys: shadys,
),
),
),
);
}
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int? screen;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Shady example',
theme: ThemeData.dark(),
home: ColoredBox(
color: Colors.black,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
PageButton(
title: 'Shadertoy samples',
shadyBuilder: (context, shady) => ShadyCanvas(shady),
shadys: shaderToyShaders,
),
PageButton(
title: 'Image samples',
shadyBuilder: (context, shady) => ShadyCanvas(shady),
shadys: imageShaders,
),
PageButton(
title: 'Interactive samples',
shadyBuilder: (context, shady) => ShadyInteractive(
shady,
uniformVec2Key: 'inputCoord',
),
shadys: interactiveShaders,
),
],
),
),
);
}
}
void main() {
runApp(const MyApp());
}