Crate renderling

Source
Expand description
renderling mascot

renderling is a “GPU driven” renderer with a focus on simplicity and ease of use, targeting WebGPU.

Shaders are written in Rust using rust-gpu.

§Hello triangle

Here we’ll run through the classic “hello triangle”, which will display a colored triangle.

§Context creation

First you must create a [Context]. The Context holds the render target - either a native window, an HTML canvas or a texture.

use renderling::{context::Context, stage::Stage, geometry::Vertex};

// create a headless context with dimensions 100, 100.
let ctx = futures_lite::future::block_on(Context::headless(100, 100));

[Context::headless] creates a Context that renders to a texture.

[Context::from_winit_window] creates a Context that renders to a native window.

[Context::try_new_with_surface] creates a Context that renders to any [wgpu::SurfaceTarget].

See the renderling::context module documentation for more info.

§Staging resources

We then create a “stage” to place the camera, geometry, materials and lights.

let stage: Stage = ctx
    .new_stage()
    .with_background_color([1.0, 1.0, 1.0, 1.0])
    // For this demo we won't use lighting
    .with_lighting(false);

The Stage is neat in that it allows you to “stage” data directly onto the GPU. Those values can be modified on the CPU and synchronization will happen during Stage::render.

Use one of the many Stage::new_* functions to stage data on the GPU:

In order to render, we need to “stage” a Primitive, which is a bundle of rendering resources, roughly representing a singular mesh.

But first we’ll need a list of Vertex organized as triangles with counter-clockwise winding. Here we’ll use the builder pattern to create a staged Primitive using our vertices.

We’ll also create a Camera so we can see the stage.

let vertices = stage.new_vertices([
    Vertex::default()
        .with_position([0.0, 0.0, 0.0])
        .with_color([0.0, 1.0, 1.0, 1.0]),
    Vertex::default()
        .with_position([0.0, 100.0, 0.0])
        .with_color([1.0, 1.0, 0.0, 1.0]),
    Vertex::default()
        .with_position([100.0, 0.0, 0.0])
        .with_color([1.0, 0.0, 1.0, 1.0]),
    ]);
let triangle_prim = stage
    .new_primitive()
    .with_vertices(vertices);

let camera = stage.new_camera().with_default_ortho2d(100.0, 100.0);

§Rendering

Finally, we get the next frame from the context with [Context::get_next_frame]. Then we render to it using Stage::render and then present the frame with [Frame::present].

let frame = ctx.get_next_frame().unwrap();
stage.render(&frame.view());
let img = futures_lite::future::block_on(frame.read_image()).unwrap();
frame.present();

Here for our purposes we also read the rendered frame as an image. Saving img should give us this:

renderling hello triangle

§Modifying resources

Later, if we want to modify any of the staged values, we can do so through each resource’s struct, using set_*, modify_* and with_* functions.

The changes made will be synchronized to the GPU at the beginning of the next Stage::render function.

§Removing and hiding primitives

To remove primitives from the stage, use Stage::remove_primitive. This will remove the primitive from rendering entirely, but the GPU resources will not be released until all clones have been dropped.

If you just want to mark a Primitive invisible, use Primitive::set_visible.

§Releasing resources

GPU resources are automatically released when all clones are dropped. The data they occupy on the GPU is reclaimed during calls to Stage::render. If you would like to manually reclaim the resources of fully dropped resources without rendering, you can do so with Stage::commit.

§Ensuring resources are released

Keep in mind that many resource functions (like Primitive::set_material for example) take another resource as a parameter. In these functions the parameter resource is cloned and held internally. This is done to keep resources that are in use from being released. Therefore if you want a resource to be released, you must ensure that all references to it are removed. You can use the remove_* functions on many resources for this purpose, like Primitive::remove_material, for example, which would remove the material from the primitive. After that call, if no other primitives are using that material and the material is dropped from user code, the next call to Stage::render or Stage::commit will reclaim the GPU resources of the material to be re-used.

Other resources like Vertices, Indices, Transform, NestedTransform and others can simply be dropped.

§Next steps

For further introduction to what renderling can do, take a tour of the Stage type, or get started with the manual.

§WARNING

This is very much a work in progress.

Your mileage may vary, but I hope you get good use out of this library.

PRs, criticisms and ideas are all very much welcomed at the repo.

😀☕

Re-exports§

pub extern crate glam;

Modules§

atlas
Texture atlas.
bloom
Physically based bloom.
bvol
Bounding volumes and culling primitives.
camera
Camera projection, view and utilities.
color
Color utils.
context
Rendering context initialization
convolution
Convolution shaders.
cubemap
Cubemap utilities.
cull
Compute based culling.
debug
Debug overlay.
draw
Handles queueing draw calls.
geometry
Types and functions for staging geometry.
gltf
GLTF support.
internal
Internal types and functions.
light
Lighting effects.
linkage
Provides convenient wrappers around renderling shader linkage.
material
Atlas images, used for materials. CPU and GPU.
math
Mathematical helper types and functions.
pbr
“Physically based” types and functions.
primitive
Mesh primitives
sdf
SDF functions for use in shaders.
skybox
Rendering skylines at infinite distances.
stage
Scene staging.
sync
GPU locks and atomics.
texture
Wrapper around [wgpu::Texture].
tonemapping
Tonemapping from an HDR texture to SDR.
transform
Decomposed 3d transforms and hierarchies.
tutorial
Shaders used in the contributor intro tutorial and in WASM tests.
types
Type level machinery.
ui
User interface rendering.

Macros§

println
A wrapper around std::println that is a noop on the GPU.

Functions§

capture_gpu_frame