Grafo
Grafo is a GPU-accelerated rendering library for Rust. It’s a quick way to render shapes and images, with masking and hierarchical clipping built in.
The library is designed for flexibility and ease of use, making it suitable for a wide range of applications, from simple graphical interfaces to complex rendering engines.
Features
- Shape Rendering: Create and render vector shapes (with optional texture layers).
- (Text rendering was previously integrated; it has now been extracted into a separate crate - https://crates.io/crates/protextinator)
- Stencil Operations: Advanced stencil operations for clipping and masking.
- Shape hierarchy: Attach shapes to parent nodes and choose whether each parent clips descendants.
- Per-instance data: Set transform and color per shape instance (no fill color stored on geometry).
- Antialiasing: You can choose between built-in support of inflated geometry or MSAA
Grafo is available on crates.io, and API Documentation is available on docs.rs.
Getting Started
Add the following to your Cargo.toml:
[]
= "0.10"
= "0.30" # For window creation and event handling
= "0.25" # For image decoding (textures)
= "0.11" # For logging
= "0.4" # For logging
Basic Usage
Below is a minimal snippet showing how to create a shape, set per-instance color and transform, and render. For a complete runnable window using winit 0.30 (ApplicationHandler API), see examples/basic.rs.
use ;
// Create a rectangle shape (no fill color on the shape itself)
let rect = rect;
renderer
.add_shape
.unwrap;
// Render one frame (typical winit loop would call this on RedrawRequested)
renderer.render.unwrap;
renderer.clear_draw_queue;
Shape hierarchy and overflow
The second argument to add_shape and add_clipping_rect is the optional
parent_shape_id. A child is drawn inside that parent in the draw tree.
By default, children are clipped to their parent:
use ;
let clipping_parent_id = renderer
.add_shape
.unwrap;
renderer
.add_shape
.unwrap;
// Let children render outside `overflow_parent_id`, while still respecting any ancestor clip.
let overflow_parent_id = renderer
.add_shape
.unwrap;
renderer
.add_shape
.unwrap;
// The same call works for ids returned by `add_clipping_rect`, so clip rectangles
// can also be used as non-clipping containers.
Examples
basic.rs– draw simple shapes (winit 0.30 ApplicationHandler)transforms.rs– demonstrates per-instance transform and color, perspective, and hit-testing
For a detailed example showcasing advanced features like hierarchical clipping and multi-layer shape texturing, please refer to the examples directory in the repository.
Multi-texturing (Background + Foreground)
Shapes support up to two texture layers that are composited with per-instance color using premultiplied alpha:
- Background layer (index 0 /
TextureLayer::Background) - Foreground layer (index 1 /
TextureLayer::Foreground)
Composition order (bottom to top):
final = foreground + (background + color * (1 - background.a)) * (1 - foreground.a)
API:
use ;
// After allocating textures via renderer.texture_manager()
renderer
.add_shape
.unwrap;
// Single-layer helper (Background):
renderer
.add_shape
.unwrap; // useful when texture transparency should reveal white
See examples/multi_texture.rs for a runnable demo that generates procedural background & foreground textures.
Positioning shapes
Use per-shape transforms to position shapes. Common helpers:
- Translate:
TransformInstance::translation(tx, ty) - Scale:
TransformInstance::scale(sx, sy) - Rotate (Z):
TransformInstance::rotation_z_deg(deg) - Compose:
a.multiply(&b)(ora.then(&b)) appliesafirst, thenb
Example:
use ShapeDrawCommandOptions;
let r = rotation_z_deg;
let t = translation;
// Rotate first, then translate
renderer
.add_shape
.unwrap;
Documentation
Documentation is available on docs.rs.
Contributing
Everyone is welcome to contribute in any way or form! For further details, please read CONTRIBUTING.md.
Authors
Also, see the list of contributors who participated in this project.
License
This project is licensed under the MIT License - see the LICENSE.md file for details