1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
//! 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.
mod gpu;
pub use gpu::WGPU;
pub use wgpu;
pub mod colorgeo;
pub mod frenderer;
pub mod meshes;
pub mod sprites;
pub use frenderer::*;
fn range<R: std::ops::RangeBounds<usize>>(r: R, hi: usize) -> std::ops::Range<usize> {
let low = match r.start_bound() {
std::ops::Bound::Included(&x) => x,
std::ops::Bound::Excluded(&x) => x + 1,
std::ops::Bound::Unbounded => 0,
};
let high = match r.end_bound() {
std::ops::Bound::Included(&x) => x + 1,
std::ops::Bound::Excluded(&x) => x,
std::ops::Bound::Unbounded => hi,
};
low..high
}
#[cfg(feature = "winit")]
mod events;
#[cfg(feature = "winit")]
pub mod input;
#[cfg(feature = "winit")]
pub use events::*;
pub mod bitfont;
pub mod nineslice;
pub mod clock;