Skip to content

Commit d72aa6a

Browse files
committed
Merge remote-tracking branch 'origin/main' into release_0.0.2
2 parents 0c5f2a8 + 480c402 commit d72aa6a

File tree

4 files changed

+78
-34
lines changed

4 files changed

+78
-34
lines changed

README.md

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,66 @@
1-
# Vega wgpu renderer
2-
This repo holds an early stage prototype of what it could look like to build an alternative [Vega](https://vega.github.io/vega/)
3-
visualization renderer in Rust using [wgpu](https://github.com/gfx-rs/wgpu). This is not useful yet (and may never be).
1+
# Avenger: A visualization engine and renderer
2+
Avenger is an early stage prototype of a new foundational rendering library for information visualization (InfoVis) systems. Avenger defines a 2D scenegraph representation tailored to the needs of InfoVis systems. To start with, the initial application of Avenger is to serve as an alternative, GPU accelerated, rendering backend for Vega visualizations.
43

5-
We're exploring how general the various components are, and so the names and structures of
6-
crates are still changing. If you're interested in collaborating on a visualization renderer for
7-
a non-Vega application, please open an issue.
4+
# Try it out in Python with Vega-Altair
5+
The `avenger` Python package provides a [custom Altair renderer](https://altair-viz.github.io/user_guide/custom_renderers.html) named `avenger-png`. This renderer relies on vl-convert to extract the vega scenegraph corresponding to a chart and then uses Avenger to render the chart to a static PNG image.
86

9-
# Try it out
7+
First, install altair, vega-datasets, avenger, and vl-convert-python
8+
```
9+
pip install -U altair vega_datasets avenger "vl-convert-python>=1.2.3"
10+
```
11+
12+
Then import Altair and activate the `avenger-png` renderer
13+
14+
```python
15+
import altair as alt
16+
alt.renderers.enable('avenger-png', scale=1)
17+
```
18+
19+
Then create and display an Altair chart as usual:
20+
21+
```python
22+
import altair as alt
23+
from vega_datasets import data
24+
25+
source = data.cars()
26+
27+
chart = alt.Chart(source).mark_circle(size=60).encode(
28+
x='Horsepower',
29+
y='Miles_per_Gallon',
30+
color='Origin',
31+
)
32+
chart
33+
```
34+
![cars_scatter.png](doc%2Fimages%2Fcars_scatter.png)
35+
36+
Or, convert the chart to a PNG rendered by Avenger:
37+
38+
```python
39+
import avenger
40+
png = avenger.altair_utils.chart_to_png(chart, scale=1)
41+
with open("scatter.png", "wb") as f:
42+
f.write(png)
43+
```
44+
## Comparison to vl-convert
45+
There aren't currently many advantages to using Avenger to render Altar charts to PNG as compared with vl-convert, which performs rendering using [resvg](https://github.com/RazrFalcon/resvg). Performance is generally comparable, though Avenger can be a bit faster for charts with a large number of symbol instances.
46+
47+
One advantage is that Avenger's text rendering support is based on [COSMIC Text](https://github.com/pop-os/cosmic-text), which supports emoji (unlike resvg's text handling). For example, here is the result of rendering the emoji example from https://altair-viz.github.io/gallery/isotype_emoji.html using Avenger:
48+
49+
![isotype_emoji.png](doc%2Fimages%2Fisotype_emoji.png)
50+
51+
# Try it out from Rust
52+
Avenger is written in Rust, and may be used directly from Rust.
1053

1154
## Run native
12-
To launch a wgpu rendered visualization in a native window, run the following:
55+
For example, to launch a wgpu rendered visualization in a native window, run the following:
1356
```
1457
cd examples/wgpu-winit
15-
cargo run
58+
cargo run --release
1659
```
1760

1861
## Build wasm
62+
Avenger may be compiled to WASM with rendering performed in WebGL2. Note that image and text marks aren't yet supported under WASM.
63+
1964
To build the example above to WASM + WebGL2, run the following:
2065
```
2166
cd examples/wgpu-winit
@@ -26,27 +71,24 @@ Then open `examples/wgpu-winit/index.html` in a web browser.
2671

2772
## Export PNG
2873
The `PngCanvas` struct can be used to convert a scene graph to a PNG image headlessly. See the tests in
29-
vega-wgpu-renderer/tests/test_image_baselines.rs for usage.
30-
31-
# Motivation
32-
Vega currently ships with two renderers: `svg` (which outputs SVG) and `canvas` (which renders to HTML Canvas).
33-
The hypothesis is that Canvas rendering is expensive enough for charts with large marks that there will be
34-
substantial benefit to rendering on the GPU. Admittedly, more experimentation and benchmarking is still needed to justify
35-
this hypothesis. For this use case, the wgpu renderer would be compiled to WASM and registered with Vega as a third
36-
renderer type.
37-
38-
Separately, this is an important step in the direction of developing a fully native Vega renderer. Combined with VegaFusion,
39-
most of the logic for fully native rendering (starting with the Vega spec) will be available in Rust. There will be more
40-
work to do to update VegaFusion to generate scene graphs, but this is a definite possibility.
41-
42-
Short of supporting full native rendering, this wgpu renderer may be useful to vl-convert to accelerate PNG static
43-
image export, and to VegaFusion to support serverside rendering of large marks.
44-
45-
# Testing
46-
To start with, the most valuable contribution of this project is probably the testing infrastructure. By relying on
47-
vl-convert, a collection of input Vega specs are rendered to PNG and converted to scene graphs. The GPU rendered
48-
PNG images are then compared for similarity to the baselines using structural similarity. See the `avenger-vega-test-data`
49-
crate for more information.
50-
51-
Note: These tests aren't running on GitHub Actions yet due to a `MakeWgpuAdapterError` error that
52-
needs to be diagnosed.
74+
avenger-wgpu/tests/test_image_baselines.rs for usage.
75+
76+
# How it works
77+
Avenger's core is written in Rust and is composed of the following crates:
78+
- `avenger`: The core `SceneGraph` representation that is independent of rendering backend
79+
- `avenger-vega`: Logic to construct an Avenger `SceneGraph` from a Vega scenegraph.
80+
- `avenger-wgpu`: Logic to render an Avenger `SceneGraph` using [wgpu](https://github.com/gfx-rs/wgpu).
81+
- `avenger-vega-test-data`: Crate that uses vl-convert to generate test data. For each baseline vega spec, `avenger-vega-test-data` will write out a vega scenegraph is JSON format along with a PNG rendering of the chart (which uses resvg). The tests in avenger-wgpu/tests/test_image_baselines.rs then input the scenegraph, render to PNG with `avenger-wgpu`, and compare the results to the baselines using structural similarity.
82+
- `avenger-python`: Python bindings to `avenger`, `avenger-vega`, and `avenger-wgpu` which also provides a custom Altair renderer (See above).
83+
84+
# Roadmap / Ambitions
85+
This is a hobby project with large ambitions. Where it goes will largely depend on whether other people get involved. But here are a few potential directions.
86+
- Alternative PNG export engine for vl-convert: Avenger could slot in next to resvg as an alternative png rendering engine in vl-convert. One advantage is that is supports emoji. The current Avenger performance isn't better than the current resvg approach across the board, but with some optimization this could likely be made a fair bit faster.
87+
- Alternative Vega renderer: Avenger can already be compiled to wasm (with some limitations), so it should be possible to write a little JavaScript glue code to register Avenger as a third Vega renderer (in addition to `svg` and `canvas`). Whether there would be a performance benefit to doing this is still TBD.
88+
- Vega native: Combining Avenger and [VegaFusion](https://vegafusion.io/) gets us close to being able to render Vega visualizations without JavaScript. More thought is needed, but it may make sense to add support for scales and guides (axes, legends, colorbars, etc.) to the Avenger SceneGraph. Then VegaFusion could have a mode that produces an Avenger scenegraph for rendering. To support interactive charts, Avenger could adopt Vega's Event Stream system (https://vega.github.io/vega/docs/event-streams/).
89+
- Matplotlib backend: Avenger could potentially serve as a rendering backend for Matplotlib (as an alternative to Agg) that provides GPU acceleration. See https://matplotlib.org/stable/users/explain/figure/backends.html#the-builtin-backends.
90+
- CPU rendering: The wgpu backend requires GPU support, so it would be useful to have a CPU rendering option as well. This could be based on [tinyskia](https://github.com/RazrFalcon/tiny-skia), which is what resvg uses.
91+
- SVG/PDF rendering: Renderers that produce SVG and PDF documents from the Avenger SceneGraph could be written.
92+
93+
# Call for help
94+
Do any of the ambitions above sound interesting? Are you interested in learning Rust? Please [start a discussion](https://github.com/jonmmease/avenger/discussions) and get involved.

avenger-wgpu/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ extern crate lazy_static;
44
pub mod canvas;
55
pub mod error;
66
pub mod marks;
7-
pub use marks::text::register_font_directory;
7+
8+
#[cfg(feature = "text-glyphon")]
9+
pub use crate::marks::text::register_font_directory;

doc/images/cars_scatter.png

42 KB
Loading

doc/images/isotype_emoji.png

117 KB
Loading

0 commit comments

Comments
 (0)