AgentSkillsCN

vello-classic-api

当您使用 vello_hybrid crate 进行场景绘制、wgpu/WebGL 渲染,或运用裁剪、渐变、图像等技术时,可选用此方案。

SKILL.md
--- frontmatter
name: vello-classic-api
description: Use when writing Rust code with the main vello crate for GPU-accelerated 2D rendering - drawing shapes, text, images, gradients, or setting up wgpu rendering pipelines

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

OperationMethodNotes
Create sceneScene::new()Lightweight, reusable
Reset between framesscene.reset()Required - clears all drawing commands
Fill shapescene.fill(style, transform, brush, brush_transform, &shape)
Stroke shapescene.stroke(&stroke, transform, brush, brush_transform, &shape)
Draw imagescene.draw_image(image, transform)At natural size
Draw textscene.draw_glyphs(&font)...draw(style, glyphs)Builder pattern
Push layerscene.push_layer(clip_style, blend, alpha, transform, &clip)For compositing
Push clipscene.push_clip_layer(clip_style, transform, &clip)Clipping only
Pop layerscene.pop_layer()
Combine scenesscene.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

MethodDescriptionWhen to Use
AaConfig::AreaIntegrates winding number over pixelDefault, best performance
AaConfig::Msaa88x multisamplingComplex overlapping paths
AaConfig::Msaa1616x multisamplingHighest 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

IssueCauseFix
Nothing renders / old contentMissing scene.reset()Call reset before each frame
Texture format errorWrong texture formatUse Rgba8Unorm with STORAGE_BINDING
NoCompatibleDeviceNo compute shader supportRequires modern GPU, not available on all WebGL
Layers not compositingUnbalanced push/popEvery push_layer/push_clip_layer needs pop_layer
Text not showingWrong glyph IDsUse proper font shaping (e.g., parley) to get glyph IDs