blob_flutter 1.1.0 copy "blob_flutter: ^1.1.0" to clipboard
blob_flutter: ^1.1.0 copied to clipboard

A highly customizable and performant 3D particle blob effect for Flutter.

Blob Flutter (3D Particle Blob) #

Cyberpunk Blob Banner

A high-performance, interactive 3D particle blob for Flutter.
Powered by procedural noise algorithms, multi-threaded Isolate computation, and GPU Fragment Shaders.

Flutter Dart

Platform

Pub Points Pub Likes License: MIT GitHub Stars

Codecov Pub Version Live Demo

Live Demo • Features • What's New • Quick Start • Algorithms • Controller • Error Handling • Architecture


Screenshot 1 Screenshot 3 Screenshot 5 Screenshot 4

Live Demo

Features #

  • Zero-Jank Architecture: Heavy 3D math and vertex projections run in a background Isolate for sustained 60/120 FPS.
  • Hardware-Accelerated Shaders: High-performance GPU fragment shaders for fluid color gradients and shimmer effects.
  • 9 Procedural Noise Models: Smooth waves, spiky crystals, cosmic vortex, cellular bubbles, carpet nets, and custom math formulas.
  • Fluid Touch Interaction: Natural drag rotation, mouse hover tracking, and tap dispersion with customizable hit testing.
  • Zero-Allocation Pipeline: Pre-allocated typed buffers prevent Garbage Collection (GC) pauses during animation.
  • Single GPU Draw Call: Flattens and renders thousands of particles in a single call via Canvas.drawRawPoints.

What's New #

  • Real 3D Colors (uColor3D): Shader gradients now rotate and turn with the 3D blob in real-time instead of staying fixed like a flat 2D wallpaper.
  • Depth Sorting (enableDepthSort): Back-to-front $O(N)$ sorting ensures front particles properly cover rear ones, removing visual glitching.
  • Atmospheric Depth-Cueing (enableDepthCueing): Distant particles scale down and softly fade, creating authentic depth and volume.
  • Responsive Auto-Fit (autoFit): Automatically resizes the blob to fit any screen, container, or device orientation without manual pixel calculations.
  • Fast Web Performance (isComplex): Alternates calculation frames on Flutter Web to keep single-threaded JavaScript smooth and responsive.
  • Smart Battery Saver: Automatically sleeps (0% CPU & GPU) when scrolled offscreen, when the app is minimized, or when navigating to another page.

Quick Start #

1. Install #

flutter pub add blob_flutter

2. Import #

import 'package:blob_flutter/blob_flutter.dart';

3. Use #

The simplest way to render a basic Blob:

// 1. Basic Blob with Fixed Radius
BlobFlutter(
  particleCount: 5000,
  radius: 150.0,
  pointSize: 2.0,
  noiseType: BlobNoiseType.harmonic,
  gradient: const LinearGradient(
    colors: [Colors.cyanAccent, Colors.purpleAccent],
  ),
)

// 2. Fully Responsive Blob with 3D Depth Sorting & Depth-Cueing
BlobFlutter(
  particleCount: 5000,
  autoFit: true, // Automatically resizes radius to fit parent bounds
  radiusFactor: 0.85,
  enableDepthSort: true, // Linear O(N) back-to-front depth sorting
  enableDepthCueing: true, // Realistic atmospheric perspective attenuation
  noiseType: BlobNoiseType.harmonic,
  gradient: const LinearGradient(
    colors: [Colors.cyanAccent, Colors.purpleAccent],
  ),
)

Controller Usage #

For dynamic runtime control, use the BlobController. It allows you to morph geometry, change colors, and tweak physics on the fly.

class MyBlob extends StatefulWidget {
  @override
  _MyBlobState createState() => _MyBlobState();
}

class _MyBlobState extends State<MyBlob> {
  late BlobController _controller;

  @override
  void initState() {
    super.initState();
    _controller = BlobController(
      particleCount: 5000,
      radius: 150.0,
      noiseType: BlobNoiseType.simplex,
      dampingFactor: 0.95,
      isColorAnimated: true,
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onDoubleTap: () => _controller.setNoiseType(BlobNoiseType.spiky),
      child: BlobFlutter(
        controller: _controller,
      ),
    );
  }
}

Tip

Controller Precedence & Single Source of Truth: When an external BlobController is provided to BlobFlutter, the controller serves as the single source of truth. Passing widget-level configuration properties (particleCount, radius, pointSize, speed, noiseType, gradient, etc.) alongside controller will be safely ignored with a debug-mode warning. Always configure those properties directly inside BlobController(...).


Procedural Noise Algorithms #

Choose from 9 distinct mathematical displacement models using the BlobNoiseType enum:

Algorithm Visual Characteristics Best For
harmonic Smooth, organic, fluid liquid blob motion. Liquid effects, calm assistants
spiky Sharp peaks, crystalline spikes, urchin geometry. Audio visualizers, energetic UI
fractal Multi-octave turbulent cloud and terrain details. Complex, textured surfaces
cellular Segmented clusters, biological cells, bubbles. Organic, microscopic visuals
vortex Swirling cyclone, spiral galaxy, tornado. Loading spinners, portals
sphericalHarmonics Acoustic cymatics, nodal patterns, quantum fields. High-tech, futuristic UI
simplex Omni-directional, artifact-free smooth flow. Clean, continuous deformation
wave Flat full square carpet/net with undulating wave ripples. Floating wave nets, square carpets, audio grids
custom User-defined mathematical procedural noise algorithm. Custom 3D shapes, stars, toruses, hearts, custom math

Custom Procedural Noise & 3D Math Engine #

With BlobNoiseType.custom, you have complete creative freedom to sculpt custom 3D geometries, pulsating crystals, hollow toruses, swirling spirals, or bespoke mathematical motions.

1. Custom Noise Function Signature #

A custom noise function evaluates per-particle displacement in 3D space:

typedef BlobCustomNoiseFunction = double Function(
  double px,        // Particle X on unit sphere (-1.0 to 1.0)
  double py,        // Particle Y on unit sphere (-1.0 to 1.0)
  double pz,        // Particle Z on unit sphere (-1.0 to 1.0)
  double frequency, // noiseFrequency parameter
  double time,      // Animation time in seconds
  double blobiness, // Global deformation multiplier
);

2. Built-in Math Helpers in BlobMath #

BlobMath provides high-performance, allocation-free static utilities for sculpting 3D particles:

  • BlobMath.azimuth(px, pz): Azimuthal angle $\phi = \text{atan2}(pz, px) \in [-\pi, \pi]$ (ideal for longitude/spiral twisting).
  • BlobMath.elevation(py): Elevation angle $\theta = \text{asin}(py) \in [-\pi/2, \pi/2]$ with safe clamping against NaN.
  • BlobMath.distance2D(x, z): Planar radial distance $\sqrt{x^2 + z^2}$ from the Y-axis.
  • BlobMath.fastSimplex3D(x, y, z): High-speed Simplex 3D noise for organic, terrain-like surfaces.
  • BlobMath.smoothstep(edge0, edge1, x): Hermite interpolation for smooth borders and transitions.
  • BlobMath.clampDisplacement(val): Automatic safeguard against NaN or Infinity, clamping values safely to [0.05, 5.0].

3. Usage Examples #

Via BlobController:

final controller = BlobController(
  noiseType: BlobNoiseType.custom,
  customNoise: (px, py, pz, f, time, blobiness) {
    final double phi = BlobMath.azimuth(px, pz);
    return 1.0 + sin(phi * 4.0 + time) * 0.3 * blobiness;
  },
);

// Switch or update dynamically at runtime:
controller.setCustomNoise((px, py, pz, f, time, blobiness) {
  return 1.0 + BlobMath.fastSimplex3D(px * f, py * f, pz * f + time) * 0.35 * blobiness;
});

Via BlobFlutter Widget:

BlobFlutter(
  noiseType: BlobNoiseType.custom,
  customNoise: (px, py, pz, f, time, blobiness) {
    final double r = BlobMath.distance2D(px, pz);
    return 1.0 + cos(r * 8.0 * f - time * 3.0) * 0.25 * blobiness;
  },
)

4. Golden Rules for Glitch-Free Shapes #

  1. The 1.0 Anchor: Displacements scale the unit sphere. Always write equations relative to 1.0 (e.g. 1.0 + (wave * blobiness)).
  2. Safe from NaN & Isolate Closures: Custom noise closures run synchronously on the main thread (<0.5ms for 3,000 particles), allowing you to write any lambda or closure without Isolate serialization errors. All returns are automatically protected from NaN and Infinity.
  3. Zero Heap Allocations: The function is invoked per-particle every frame. Keep all calculations on double primitives without instantiating objects or collections.

5. Practical Shape Recipes #

// 1. Classic 5-Point 3D Star
controller.setCustomNoise((px, py, pz, f, time, blobiness) {
  final double angle = atan2(py, px) + time * 0.4;
  final double star2D = max(0.0, cos(5.0 * angle));
  final double sharpPoints = pow(star2D, 2.5).toDouble();
  final double zProfile = max(0.0, 1.0 - pz.abs() * 2.0);
  return (0.45 + sharpPoints * zProfile * 1.5) * blobiness;
});


// 2. Saturn Planet & Glowing Equatorial Ring
controller.setCustomNoise((px, py, pz, f, time, blobiness) {
  final double yDist = py.abs();
  final double ring = yDist < 0.15 ? pow(0.9 - yDist / 0.35, 5.0).toDouble() * 1.5 : 0.0;
  return (0.55 + ring) * blobiness;
});


Customization Properties #

Widget Properties (BlobFlutter) #

Configure the initial state of your blob directly in the widget.

Property Type Default Description
particleCount int 5000 Total number of particles on the sphere (higher counts increase density but may affect performance).
radius double 150.0 Base radius in logical pixels.
autoFit bool false Dynamically resizes the radius to fit parent container bounds (min(w, h) / 2.0) * radiusFactor.
radiusFactor double 0.85 Multiplier applied to half the minimum container dimension when autoFit is active (leaves room for wave crests).
enableDepthSort bool true Linear $O(N)$ bucket sort in isolate; renders particles back-to-front (Painter's algorithm) to prevent depth artifacts.
enableDepthCueing bool true Dynamic perspective scaling and opacity attenuation across depth slices for authentic 3D realism.
depthCueingFactor double 0.4 Intensity of depth-cueing perspective scaling ([0.0, 1.0]).
pointSize double 2.0 Diameter of each rendered particle.
rotationX / rotationY double 0.0 Initial base 3D orientation angles (pitch & yaw) in radians.
noiseType Enum harmonic Procedural 3D noise algorithm used.
customNoise BlobCustomNoiseFunction? null Custom procedural displacement function used when noiseType is BlobNoiseType.custom.
controller BlobController? null External controller for runtime manipulation.
gradient Gradient Linear Color gradient (Linear, Radial, or Sweep) mapped in 3D object space.
isComplex bool false Enables temporal frame interleaving (striding) across alternating frames to halve per-frame CPU calculations.
webTemporalInterleaving bool true Automatically enables frame interleaving on Flutter Web to guarantee smooth 60 FPS.
maxWebParticles int? 3000 Automatic particle cap on Flutter Web to safeguard single-threaded JS performance.
autoPlay bool true Whether the animation loop starts automatically. Set to false for battery savings on static views or widget tests.
autoPauseOffscreen bool true Automatically halts ticker and isolate (0% CPU/GPU) when scrolled out of viewport.
autoPauseOnAppBackground bool true Automatically pauses when application is minimized, hidden, or in the background.
autoPauseOnRouteChange bool true Automatically pauses when navigated away from via Navigator routes (ModalRoute).
routeObserver RouteObserver? null Optional observer for navigation route transitions.
interactive bool true When false, touches pass through seamlessly to underlying widgets in a Stack.
hitTestBehavior HitTestBehavior translucent Hit-test event dispatching behavior (translucent, opaque, deferToChild).

Tip

Performance & Particle Count (particleCount): Increasing the particle count enhances visual fullness and detail, but directly increases computation time in the isolate and vertex drawing load on the GPU:

  • 1,000 – 3,000: Ideal for low-end devices, battery-sensitive apps, or subtle background elements.
  • 3,000 – 6,000 (Default: 5000): Sweet spot for smooth 60/120 FPS on most modern mobile devices.
  • 8,000 – 20,000+: Recommended for modern flagship phones, desktop, or web applications with capable GPUs.

(Note: These figures are approximations and may vary depending on target device hardware and workload).

Controller Properties (BlobController) #

Manipulate the blob dynamically at runtime using the controller methods.

Setter Method Valid Range / Type Description
pause() - Stops the animation ticker completely (0% CPU/battery usage).
resume() - Resumes the animation loop if paused.
isPaused true/false Getter checking whether the animation loop is currently paused.
setParticleCount(val) 10 - 100000 Dynamically sets particle count (reallocates buffers).
setAutoFit(val) true/false Toggles dynamic viewport-fitting radius.
setRadiusFactor(val) double Changes container dimension multiplier in auto-fit mode.
setEnableDepthSort(val) true/false Toggles isolate $O(N)$ Z-depth sorting (Painter's algorithm).
setEnableDepthCueing(val) true/false Toggles atmospheric perspective depth scaling.
setDepthCueingFactor(val) 0.0 - 1.0 Adjusts depth attenuation strength.
setIsComplex(val) true/false Enables/disables temporal frame interleaving (striding).
setWebTemporalInterleaving(val) true/false Toggles temporal frame interleaving on Web.
setMaxWebParticles(val) int? Sets or clears web particle count limit.
setBlobiness(val) 0.0 - 5.0 Amplitude of noise displacement.
setSpeed(val) 0.0 - 10.0 Playback speed of the animation.
setRotationX(val) / setRotationY(val) double (radians) Sets persistent 3D orientation pitch & yaw angles.
setRotation({x, y}) double? (radians) Sets both 3D orientation angles simultaneously.
setDispersion(val) 0.0 - 3.0 Outward radial displacement.
setNoiseFrequency(val) 0.1 - 5.0 Density of the noise ripples.
setNoiseType(type) Enum Changes the deformation algorithm.
setCustomNoise(fn, {switchToCustom}) Function? Sets custom procedural noise callback and optionally sets noiseType to custom.
setIsRainbowMode(bool) true/false Cycles colors through the HSV spectrum.
zoomIn(val) / zoomOut - Scales the blob size dynamically.

(Check the source code for a complete list of advanced physics and shader properties).


Architecture & Performance #

BlobFlutter is built with deep respect for both developers and end-user hardware. Every mathematical model, buffer allocation, and render pass is calculated with exacting precision to deliver sustained 60 / 120 FPS while safeguarding device resources, thermals, and battery life:

  1. Persistent Worker Isolate: 3D math, trigonometric deformations, and matrix rotations execute in a dedicated background worker (BlobWorker). The UI receives data via zero-copy TransferableTypedData.
  2. True 3D Object-Space Fragment Shaders (blob.frag): Rather than projecting flat 2D color coordinates across screen pixels, the GLSL fragment program reconstructs the 3D surface normal $\vec{n} = (\hat{p}_x, \hat{p}_y, \hat{p}_z)$ for each point and multiplies by the inverse pitch/yaw rotation matrix ($R^T$). Colors rotate synchronously with the 3D object in space.
  3. $O(N)$ Linear Depth Bucket Sorting: To preserve 60/120 FPS without Garbage Collection pauses, the worker isolate sorts particles using a 64-bin linear bucket sort ($O(N)$ vs $O(N \log N)$ quicksort). Combined with 4-strata atmospheric depth-cueing in BlobPainter, particles render back-to-front with depth-dependent scale and opacity.
  4. Single GPU Draw Call: Particle coordinates are flattened and drawn directly to graphics hardware using Canvas.drawRawPoints.
  5. Zero Heap Allocation: Coordinate caches, depth sorting bins, and calculation buffers are pre-allocated during initialization, avoiding Garbage Collector (GC) stutters.
  6. Web Temporal Striding (isComplex): On Flutter Web, where Dart executes on a single JavaScript event loop, temporal interleaving splits particle computations across alternating odd/even frames, reducing CPU execution time by 50% without visual stutter.
  7. Ultra-Fast Path Engine: During steady-state animations (when no pointers or radial dispersions are active), the math loop transitions into an unbranched, streamlined execution path, eliminating redundant pointer and touch checks per frame.
  8. Multi-Tier Zero-Battery Lifecycle: Tickers and isolate computations automatically shut down (0% CPU/GPU usage) when scrolled offscreen, when the app enters the background, or when navigating to another route via ModalRoute / RouteObserver.

Note

Performance Scaling: Although computation is offloaded to a background Isolate to keep the UI thread jank-free, mathematical transformations and GPU vertex throughput scale linearly with particleCount. Very high counts on budget or older hardware may impact frame rates or cause battery drain.


Error Handling #

BlobFlutter provides actionable console diagnostics with automatic CPU fallback if shaders are unavailable. Catch issues programmatically or render custom fallback interfaces via onError and errorBuilder.


Built with ❤️ by dexter for fluid,interactive Flutter interfaces.
24
likes
160
points
501
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A highly customizable and performant 3D particle blob effect for Flutter.

Repository (GitHub)
View/report issues

Topics

#graphics #animation #particles #shaders #widget

License

MIT (license)

Dependencies

flutter

More

Packages that depend on blob_flutter