vello Reference
GPU-accelerated 2D vector renderer using compute shaders. Requires wgpu with compute shader support. Coordinates are in pixels with origin at top-left, Y increasing downward.
Quick Reference
| Operation | Method | Notes |
|---|---|---|
| Create scene | Scene::new() | Lightweight, reusable |
| Reset between frames | scene.reset() | Required - clears all drawing commands |
| Fill shape | scene.fill(style, transform, brush, brush_transform, &shape) | |
| Stroke shape | scene.stroke(&stroke, transform, brush, brush_transform, &shape) | |
| Draw image | scene.draw_image(image, transform) | At natural size |
| Draw text | scene.draw_glyphs(&font)...draw(style, glyphs) | Builder pattern |
| Push layer | scene.push_layer(clip_style, blend, alpha, transform, &clip) | For compositing |
| Push clip | scene.push_clip_layer(clip_style, transform, &clip) | Clipping only |
| Pop layer | scene.pop_layer() | |
| Combine scenes | scene.append(&other, transform) | O(N) operation |
Rendering Setup
rust
use vello::{Renderer, RendererOptions, RenderParams, AaConfig, Scene};
use vello::peniko::color::palette;
// Create renderer (once per device)
let renderer = Renderer::new(&device, RendererOptions::default())?;
// Each frame:
scene.reset(); // Required!
// ... add drawing commands ...
renderer.render_to_texture(
&device,
&queue,
&scene,
&texture_view, // Must be Rgba8Unorm with STORAGE_BINDING
&RenderParams {
base_color: palette::css::BLACK,
width,
height,
antialiasing_method: AaConfig::Area, // Recommended default
},
)?;
Drawing Shapes
rust
use vello::kurbo::{Affine, Circle, Rect, RoundedRect, Line, Stroke};
use vello::peniko::{Color, Fill};
// Fill
scene.fill(
Fill::NonZero, // or Fill::EvenOdd
Affine::IDENTITY,
Color::new([0.9, 0.5, 0.6, 1.0]), // RGBA
None, // brush_transform
&Circle::new((200.0, 200.0), 100.0),
);
// Stroke
let stroke = Stroke::new(4.0)
.with_caps(vello::kurbo::Cap::Round)
.with_join(vello::kurbo::Join::Round);
scene.stroke(&stroke, Affine::IDENTITY, color, None, &rect);
Gradients
rust
use vello::peniko::{Gradient, ColorStop, Extend};
use vello::peniko::color::palette;
let gradient = Gradient::new_linear((0.0, 0.0), (100.0, 100.0))
.with_stops([
ColorStop::from((0.0, palette::css::RED)),
ColorStop::from((1.0, palette::css::BLUE)),
])
.with_extend(Extend::Pad); // Pad, Repeat, or Reflect
scene.fill(Fill::NonZero, transform, &gradient, None, &shape);
Images
rust
use vello::peniko::{ImageData, ImageBrush, Blob};
let image = ImageData {
data: Blob::new(Arc::new(rgba_bytes)),
format: peniko::ImageFormat::Rgba8,
alpha_type: peniko::ImageAlphaType::Alpha,
width,
height,
};
// Draw at natural size
scene.draw_image(&image, Affine::translate((x, y)));
// Or fill shape with image brush
scene.fill(Fill::NonZero, transform, ImageBrush::new(image), None, &rect);
GPU-Resident Textures
rust
// Register wgpu texture (Rgba8Unorm with COPY_SRC) let image = renderer.register_texture(texture); scene.draw_image(&image, transform); // Cleanup when done renderer.unregister_texture(image);
Text
rust
use vello::{Glyph, DrawGlyphs};
use vello::peniko::{FontData, color::palette};
let font_data = FontData::new(Blob::new(Arc::new(font_bytes)), 0);
scene.draw_glyphs(&font_data)
.font_size(24.0)
.transform(Affine::translate((x, y)))
.brush(palette::css::WHITE)
.draw(
Fill::NonZero,
glyphs.iter().copied(), // Iterator of Glyph { id, x, y }
);
Layers and Clipping
rust
use vello::peniko::{BlendMode, Compose};
// Compositing layer with blend mode
scene.push_layer(
Fill::NonZero, // clip_style
BlendMode::Multiply, // or Compose::SrcOver, etc.
0.5, // alpha
Affine::IDENTITY,
&clip_shape,
);
// ... draw content ...
scene.pop_layer();
// Simple clipping (no blend mode overhead)
scene.push_clip_layer(Fill::NonZero, transform, &clip_path);
// ... draw clipped content ...
scene.pop_layer();
Anti-Aliasing Options
| Method | Description | When to Use |
|---|---|---|
AaConfig::Area | Integrates winding number over pixel | Default, best performance |
AaConfig::Msaa8 | 8x multisampling | Complex overlapping paths |
AaConfig::Msaa16 | 16x multisampling | Highest quality |
Configure at renderer creation with RendererOptions::antialiasing_support.
Imports
rust
// Core
use vello::{Scene, Renderer, RendererOptions, RenderParams, AaConfig};
// Geometry (re-exported from kurbo)
use vello::kurbo::{Affine, Point, Vec2, Rect, Circle, Ellipse, Line, RoundedRect, BezPath, Stroke};
// Styling (re-exported from peniko)
use vello::peniko::{
Color, Fill, BlendMode, Compose,
Brush, Gradient, ColorStop, Extend,
ImageData, ImageBrush, ImageFormat, ImageAlphaType,
FontData,
};
use vello::peniko::color::palette; // Named colors: palette::css::RED, etc.
// Text
use vello::{Glyph, DrawGlyphs};
// wgpu integration
use vello::wgpu;
use vello::util::{RenderContext, RenderSurface}; // Helpers for windowed apps
Pitfalls
| Issue | Cause | Fix |
|---|---|---|
| Nothing renders / old content | Missing scene.reset() | Call reset before each frame |
| Texture format error | Wrong texture format | Use Rgba8Unorm with STORAGE_BINDING |
NoCompatibleDevice | No compute shader support | Requires modern GPU, not available on all WebGL |
| Layers not compositing | Unbalanced push/pop | Every push_layer/push_clip_layer needs pop_layer |
| Text not showing | Wrong glyph IDs | Use proper font shaping (e.g., parley) to get glyph IDs |