aquarelle
Watercolor-style soft-bleed orb rendering on a tiny_skia::Pixmap.
Given a center, a radius, an RGB color, and a u64 seed, aquarelle
composites a calm cel-anime night-scene orb onto a pixel buffer you
already own. Four orthogonal knobs — bleed, bloom, offset,
halo — let you tune from a flat soft orb to a hazy paper-bleed
light source.
Originally written as the texture set inside the
orber abstract-mood-image
generator; lifted into its own crate so other watercolor / sumi
renderers (e.g. blueprinter) can share the same engine.
Install
[]
= "0.2"
Example: orb rendering
use ;
use ;
let mut pix = new.unwrap;
pix.fill;
render_aquarelle_orb;
// `pix.data()` is now BGRA bytes you can write to PNG, send to
// WebCodecs, copy to a GPU texture, etc.
Example: bleed pass over an existing picture (v0.2)
Use render_aquarelle_bleed_pass when the pixmap already contains your
art (e.g. ink strokes from blueprinter) and you want a soft halo
underneath the existing pixels.
use ;
use ;
let mut pix = new.unwrap;
pix.fill;
// Draw a black dot to bleed.
let mut paint = default;
paint.set_color_rgba8;
let mut pb = new;
pb.push_circle;
let path = pb.finish.unwrap;
pix.fill_path;
render_aquarelle_bleed_pass;
A 3-pass box blur approximates a Gaussian; a faint seed-derived paper grain is multiplied onto the blurred layer; the original picture is then re-composited on top.
The four elements
| Knob | Range | What it does |
|---|---|---|
bleed |
0.0 .. 1.0 |
Number and size of same-color satellite gradients scattered around the orb (film grain / paper bleed). |
bloom |
0.0 .. 1.0 |
A near-white core inside the inner ~30 % of the radius so the orb reads as a light source. |
offset |
0.0 .. 1.0 |
Decouples the gradient center from the geometric center by up to 25 % of the radius along a seed-derived angle. |
halo |
0.0 .. 1.0 |
Saturation boost on the outer falloff (film halation feel). |
AquarelleParams::default() sets every knob to 0.5 for a calm
mid-strength orb.
Renderer-agnostic on purpose
aquarelle does not know what's already on the pixmap, what the
rest of your scene looks like, or how you intend to encode the
result. It composites four watercolor layers onto the buffer you
hand it; you decide background fill, layout, output format. This
keeps the crate usable from CLIs (PNG via image), browser
visualizers (OffscreenCanvas + wasm-bindgen), and animation
pipelines (frame-by-frame Pixmap reuse) with the same code.
Determinism
Identical (center, radius, color, seed, params) produce
byte-identical pixels. Internal RNG is seeded per call via
ChaCha8Rng::seed_from_u64(seed) and never touches thread_rng,
so animation pipelines that re-render the same orb every frame
get a stable visual.
wasm friendliness
The crate's only dependencies are tiny-skia, palette, rand,
and rand_chacha — all wasm-compatible. It is used in production
from orber-wasm
on Cloudflare Pages.
Status
- v0.2.0 — adds
render_aquarelle_bleed_passfor bleeding an existing rasterized picture (3-pass box blur Gaussian approximation + halo saturation boost + seed-derived paper grain). The originalrender_aquarelle_orbAPI is unchanged. See Issue #2. - v0.1.0 — extracted from
orber-core v0.3.x's in-treeaquarellemodule, where it has been in production since 2026-04 (seeorberPR #30 / Issue #8). API is stable; the breakout closes orber Issue #10 and unblocksblueprinteradopting the same texture set.
License
MIT