import 'dart:typed_data';
import 'dart:ui' as ui;
import 'dart:math' as math;
import 'dart:async';
import 'package:flutter/animation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:vector_math/vector_math.dart';
const OCTAVES = 6;
double fract(double x) {
return x - x.floor();
}
double random(Vector2 st) {
return fract(math.sin(dot2(st.xy, Vector2(12.9898, 78.233))) * 43758.5453123);
}
double noise(Vector2 st) {
Vector2 i = Vector2(st.x.floor().toDouble(), st.y.floor().toDouble());
Vector2 f = Vector2(fract(st.x), fract(st.y));
double a = random(i + Vector2(0.0, 0.0));
double b = random(i + Vector2(1.0, 0.0));
double c = random(i + Vector2(0.0, 1.0));
double d = random(i + Vector2(1.0, 1.0));
Vector2 u = Vector2(
smoothStep(0.0, 1.0, f.x),
smoothStep(0.0, 1.0, f.y),
);
double result =
mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
return result;
}
double fbm(Vector2 st) {
double value = 0.0;
double amplitude = .5;
for (int i = 0; i < OCTAVES; i++) {
value += amplitude * noise(st);
st *= 2.0;
amplitude *= 0.5;
}
return value;
}
class NonStopVSync implements TickerProvider {
const NonStopVSync();
Ticker createTicker(TickerCallback onTick) => Ticker(onTick);
}
const alphaOffset = 24;
const redOffset = 16;
const greenOffset = 8;
const blueOffset = 0;
const kImageDimension = 60;
int makeColor(double time, int x, int y) {
// main function of GLSL.
int red = 0;
int green = 0;
int blue = 0;
int alpha = 255;
int resultColor = 0;
Vector2 p = Vector2(
(x.toDouble() * 2 - kImageDimension) / kImageDimension,
(y.toDouble() * 2 - kImageDimension) / kImageDimension,
);
// color processing here
double primary = fbm(p * 2.0);
Vector2 secondary = Vector2(
p.x + primary + time,
p.y + primary + time,
);
red = (fbm(secondary) * 255).toInt();
green = red;
blue = red;
// convert 8bit integers to 32bit integers
resultColor += (alpha << alphaOffset);
resultColor += (red << redOffset);
resultColor += (green << greenOffset);
resultColor += (blue << blueOffset);
return resultColor;
}
Future<ui.Image> makeImage({double time = 0}) {
final c = Completer<ui.Image>();
final pixels = Int32List(kImageDimension * kImageDimension);
int x = 0;
int y = 0;
for (int i = 0; i < pixels.length; i++) {
y = (i / kImageDimension).floor();
x = i % kImageDimension;
pixels[i] = makeColor(time, x, y);
}
ui.decodeImageFromPixels(
pixels.buffer.asUint8List(),
kImageDimension,
kImageDimension,
ui.PixelFormat.rgba8888,
c.complete,
);
return c.future;
}
void main() async {
const imageSize = 60.0;
final RenderImage image = RenderImage(
width: imageSize,
height: imageSize,
image: await makeImage(),
);
final RenderBox imageWrap = RenderConstrainedBox(
additionalConstraints:
const BoxConstraints.tightFor(width: imageSize, height: imageSize),
child: image,
);
final RenderBox root = RenderPositionedBox(
alignment: Alignment.center,
child: imageWrap,
);
RenderingFlutterBinding(root: root);
final AnimationController animation = AnimationController(
duration: const Duration(milliseconds: 800),
vsync: const NonStopVSync(),
)..repeat();
double time = 0.0;
animation.addListener(() async {
image.image = await makeImage(time: time);
time += 0.01;
});
}
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.