-
Notifications
You must be signed in to change notification settings - Fork 53
docs(js): Clarify webgl2 vs canvas2d caveats for web runtime and choosing one over the other #866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,73 +1,76 @@ | ||
| --- | ||
| title: "Canvas vs WebGL2" | ||
| description: "Choose between `@rive-app/webgl2` and `@rive-app/canvas`, with guidance on performance, package size, and when to use canvas-lite." | ||
| description: "Choose between the @rive-app/webgl2 and @rive-app/canvas runtime packages." | ||
| --- | ||
|
|
||
| ### Choose a runtime | ||
| Rive's web runtime comes in two main packages: [`@rive-app/webgl2`](https://www.npmjs.com/package/@rive-app/webgl2) and [`@rive-app/canvas`](https://www.npmjs.com/package/@rive-app/canvas). They expose the same API. The only difference is how they draw. | ||
|
|
||
| For web, start by choosing one of these two packages: | ||
| **For most use cases, use `@rive-app/webgl2`.** It draws with the Rive Renderer, the same renderer as the Rive Editor, so everything you can author in Rive renders the way you designed it. `@rive-app/canvas` uses the browser's own 2D renderer, which brings its own advantages (particularly for performance), but it does not yet support every Editor feature. | ||
|
|
||
| - [`@rive-app/webgl2`](https://www.npmjs.com/package/@rive-app/webgl2) | ||
| - [`@rive-app/canvas`](https://www.npmjs.com/package/@rive-app/canvas) | ||
| Switching is a one-line import change, so you can try both and measure against your own content. | ||
|
|
||
| They share the same high-level API, so switching packages does not require changing how you create a `new Rive({...})` instance. The key differences are the renderer and package size; read the sections below to decide what is best for your use case, and compare package sizes on [Runtime Sizes](/runtimes/runtime-sizes/). | ||
| ## Comparison | ||
|
|
||
| ### `@rive-app/webgl2` (recommended) | ||
| | | `@rive-app/webgl2` (recommended) | `@rive-app/canvas` | | ||
| | --- | --- | --- | | ||
| | Draws with | The [Rive Renderer](https://rive.app/renderer?utm_source=docs&utm_medium=content) on WebGL2 | The browser's [Canvas2D](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) API | | ||
| | [Vector Feathering](/editor/fundamentals/fill-and-stroke#vector-feathering) | ✅ Supported | ❌ Not yet supported; planned for a future release | | ||
| | Editor fidelity | ✅ The same renderer the Rive Editor uses | 🟡 Matches for nearly all content (see [Fill Rules](#fill-rules)) | | ||
| | Blend modes | 🟡 All blend modes, but anything other than **Normal** is expensive (see [Performance](#performance)) | ✅ All blend modes, at no extra cost | | ||
| | Graphics per page | 🟡 Bound by the browser's WebGL context limit (see [WebGL Context Limits](#webgl-context-limits)) | ✅ No practical limit | | ||
|
|
||
| Use `@rive-app/webgl2` if you want the best rendering quality and performance in most cases. | ||
| ## Other notable tradeoffs | ||
|
|
||
| ```bash | ||
| npm install @rive-app/webgl2 | ||
| ### WebGL Context Limits | ||
|
|
||
| Note that if you're using `@rive-app/webgl2`, browsers cap how many WebGL contexts a page can hold at once. The exact number varies by browser and device, and the oldest context is typically dropped once the cap is reached — which limits how many `new Rive({...})` instances you can run. See [WebGL Context Limits](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_context_limits) for more details. | ||
|
|
||
| If you show several graphics on one page, set `useOffscreenRenderer: true` on each Rive object. Every instance then shares a single offscreen context instead of creating its own, which keeps you under the cap: | ||
|
|
||
| ```javascript | ||
| const r = new rive.Rive({ | ||
| src: "https://cdn.rive.app/animations/vehicles.riv", | ||
| canvas: document.getElementById("canvas"), | ||
| useOffscreenRenderer: true, | ||
| }); | ||
| ``` | ||
|
|
||
| - Uses the [Rive Renderer](https://rive.app/renderer?utm_source=docs&utm_medium=content) for the best rendering performance | ||
| - Supports Rive Renderer-only features (for example, vector feathering) | ||
| This limit does not apply to `@rive-app/canvas`. | ||
|
|
||
| <Note> | ||
| WebGL has browser limits on concurrent contexts, which can limit how many `new Rive({...})` instances you can run at once. If you display many graphics on the same page, set `useOffscreenRenderer: true` for each Rive object. | ||
| This moves rendering work to a shared offscreen WebGL context instead of creating as many separate contexts on visible canvases, which helps avoid context-limit issues and improves stability when many Rive instances are active. | ||
| </Note> | ||
|
|
||
| <Note> | ||
| Enabling the draft | ||
| [WEBGL_shader_pixel_local_storage](https://www.wikihow.tech/Enable-WebGL-Draft-Extensions-in-Google-Chrome) | ||
| extension in Chrome improves rendering performance. Without it, Rive falls | ||
| back to an MSAA-based WebGL2 path. We are actively working with browser | ||
| vendors to make this enabled by default. | ||
| </Note> | ||
| ### Fill Rules | ||
|
|
||
| ### `@rive-app/canvas` | ||
| `@rive-app/canvas` uses the Canvas2D renderer, which offers the non-zero and even-odd [fill rules](/editor/fundamentals/fill-and-stroke#fill-rule), so Rive's clockwise fill rule draws as non-zero. The result is identical unless a path has self-intersecting, reversed, or overlapping contours. This applies to both fills and clipping paths. | ||
|
|
||
| Use `@rive-app/canvas` when your graphics are less complex and you want a smaller runtime package. | ||
| ## Performance | ||
|
|
||
| ```bash | ||
| npm install @rive-app/canvas | ||
| ``` | ||
| Today, `@rive-app/webgl2` draws through a multisample anti-aliasing (MSAA) path. | ||
|
|
||
| The Rive Renderer has a faster path to draw that relies on a GPU capability Metal and Vulkan already expose to native apps. On web browsers, it comes from [`WEBGL_shader_pixel_local_storage`](https://www.khronos.org/registry/webgl/extensions/WEBGL_shader_pixel_local_storage/), a draft WebGL extension that Rive is helping to standardize. As browsers adopt it, `@rive-app/webgl2` will pick it up automatically and draw faster. | ||
|
|
||
| Until then, blend modes are where you may notice a difference. On the MSAA path, any blend mode other than **Normal** forces the renderer to re-read the frame as it draws, and that cost adds up quickly on mobile browsers. `@rive-app/canvas` has no equivalent cost, because Canvas2D blends natively. | ||
|
|
||
| In practice: | ||
|
|
||
| - Uses the browser's built-in [CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) renderer | ||
| - Smaller package size than the WebGL2 renderer option | ||
| - Good for simpler vector/raster graphics | ||
| - Blend modes on mobile are the case where `@rive-app/canvas` can be meaningfully faster. If your file leans on them and does not use Vector Feathering, it is worth comparing the two. | ||
| - Measure on real devices. Swapping packages is a one-line change, so testing both is cheap. | ||
|
|
||
| ### More options after your runtime choice | ||
| ## Canvas Package Variants | ||
|
|
||
| For the canvas-based runtime option, you can alternatively use these variants based on packaging needs. | ||
| Two variants of the canvas package are available if you have specific bundling needs. | ||
|
|
||
| #### `@rive-app/canvas-lite` variant | ||
| ### `@rive-app/canvas-lite` | ||
|
|
||
| The canvas version of our runtime supports a `-lite` variant for smaller package size. | ||
| [`@rive-app/canvas-lite`](https://www.npmjs.com/package/@rive-app/canvas-lite) is the smallest Rive web package. It has the same API and renderer as `@rive-app/canvas`, but drops the text, layout, audio, and scripting engines to save space. | ||
|
|
||
| - Example: [`@rive-app/canvas-lite`](https://www.npmjs.com/package/@rive-app/canvas-lite) | ||
| - Use this package when you want the smallest runtime footprint | ||
| - This package variant removes some features (for example, text, layout, audio, and scripting engines) | ||
| Use it when your files do not rely on those features. If a file does use them, the affected content will not appear. | ||
|
|
||
| #### `@rive-app/canvas-single` variant | ||
| ### `@rive-app/canvas-single` | ||
|
|
||
| The canvas version of our runtime supports a `-single` variant, which bundles `rive.wasm` directly into the JavaScript file. | ||
| [`@rive-app/canvas-single`](https://www.npmjs.com/package/@rive-app/canvas-single) bundles `rive.wasm` directly into the JavaScript file, so loading Rive takes one network request instead of two. | ||
|
|
||
| - Example: [`@rive-app/canvas-single`](https://www.npmjs.com/package/@rive-app/canvas-single) | ||
| - Use this package if you want to avoid a separate WASM network request | ||
| - Expect a larger JS bundle compared to the standard package | ||
| Use it when you want to avoid a separate WASM request. The tradeoff is a larger JavaScript bundle. | ||
|
|
||
| ### Deprecated package | ||
| ## Deprecated Package | ||
|
|
||
| `@rive-app/webgl` is deprecated and will no longer receive updates after `v2.37.0`. Prefer `@rive-app/webgl2`. | ||
| `@rive-app/webgl` is deprecated and receives no updates after `v2.37.0`. Move to `@rive-app/webgl2`, or to `@rive-app/canvas` if your file does not need the Rive Renderer. Neither move requires API changes — see the [migration guide](/runtimes/web/migration-guides). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.