53 releases (7 breaking)

2.0.3 Oct 10, 2023
0.9.14 Apr 12, 2024
0.9.13 Mar 19, 2024
0.7.9 Dec 1, 2023
0.5.8 Apr 25, 2022

#265 in Graphics APIs

Download history 12/week @ 2024-01-29 2/week @ 2024-02-05 438/week @ 2024-02-12 340/week @ 2024-02-19 515/week @ 2024-02-26 648/week @ 2024-03-04 109/week @ 2024-03-11 187/week @ 2024-03-18 313/week @ 2024-04-01

634 downloads per month
Used in frapp




  • Optimized tile renderer for frenderer
  • more postprocessing examples


A friendly, modular renderer built with WGPU.

Frenderer can be used in three ways (not mutually exclusive):

  1. As a collection of standalone rendering strategies for sprites, textured meshes, and flat-colored meshes.
  2. As a cross-platform wrapper over WGPU initialization and state management, offering a convenient render() function.
  3. As an application framework (with the winit feature) to give reasonable defaults for game simulation and rendering lifecycle.

The entry point for frenderer will depend on how it's being used; for use case (1), you can initialize a WGPU struct yourself with an adapter, device, and queue, and proceed to use the built-in sprites::SpriteRenderer, meshes::MeshRenderer, meshes::FlatRenderer, or colorgeo::ColorGeo color-geometry postprocessing transform with your own renderpass. In use case (2), you can initialize a Renderer asynchronously with a given size, WGPU instance, and GPU surface, and call Renderer::render to handle all the drawing; or you can let events::Driver manage your application's event loop and initialize frenderer at the appropriate time (with the winit feature flag). Finally, in use case (3), you'll use clock::Clock, the extension trait in events::FrendererEvents, and the input::Input struct to simplify your game loop's lifecycle.

frenderer is highly modular, especially in case (1); in particular, frenderer does not need to take control of the event loop from winit or exclusively own the WGPU instance, device, or adapter. For convenience, users who don't need this modularity can employ Driver to initialize the window and a renderer. Once you have obtained a frenderer::Renderer, you can call e.g. [Renderer::sprite_group_add()] to set up a 2D render group and eventually call [frenderer::Renderer::sprites_mut()] or [frenderer::Renderer::sprite_group_resize()] to modify the sprite data and frenderer::Renderer::render to draw.

The 3D rendering facilities of frenderer are pretty basic at the moment, with simple perspective cameras and unlit textured or flat-colored meshes. As in the sprite renderer, the overriding performance concern has been to minimize pipeline state changes and draw calls using features like instanced rendering, storage buffers (where available), array textures, and packing multiple meshes into a single buffer.

Frenderer works in retained mode, but the "engine-immediate" example shows how an immediate-mode render API could be built on top of it.


~782K SLoC