Crate renderling

Source
Expand description

A “GPU driven” renderer with a focus on simplicity and ease of use. Backed by WebGPU.

Shaders are written in Rust using rust-gpu.

All data is staged on the GPU using a slab allocator.

§Hello triangle

First you must create a crate::context::Context.

use renderling::Context;

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

Then create a stage to place your camera, geometry, materials and lights.

use renderling::stage::Stage;
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 place values and arrays of values directly onto the GPU. Those values can be modified on the CPU and synchronization will happen during Stage::render. These values are called Hybrids and HybridArrays.

use renderling::slab::{Hybrid, HybridArray};

let an_f32: Hybrid<f32> = stage.new_value(1337.0);

let an_array_of_tuples: HybridArray<(f32, u32, bool)> =
    stage.new_array([(0.0, 0, false), (1.0, 1, true)]);

In order to render, we need to “stage” a Renderlet, which is a bundle of rendering resources. We do this in the same way we “staged” an_f32 above.

But first we’ll need a Camera and some vertices of Vertex organized as triangles with counter-clockwise winding.

use renderling::{
    camera::Camera,
    stage::{Renderlet, Vertex},
};
let camera = stage.new_value(Camera::default_ortho2d(100.0, 100.0));
let vertices = stage.new_array([
    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 = stage.new_value(Renderlet {
    camera_id: camera.id(),
    vertices_array: vertices.array(),
    ..Default::default()
});

This gives us triangle, which is a Hybrid<Renderlet>. We can now pass triangle to the stage to draw each frame using Stage::add_renderlet.

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

stage.add_renderlet(&triangle);

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

Saving img should give us this:

renderling hello triangle

§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.

😀☕

Modules§

atlas
Texture atlas.
bits
Helpers for bitwise operations.
bloom
Physically based bloom.
camera
Camera projection, view and utilities.
color
Color utils.
convolution
Convolution shaders.
cubemap
Render pipelines and layouts for creating cubemaps.
ibl
Resources for image based lighting.
math
Mathematical helper types and functions.
pbr
“Physically based” types and functions.
prelude
A prelude, meant to be glob-imported.
skybox
Skybox shaders and CPU code.
slab
GPU and CPU slab allocation.
stage
GPU staging area.
texture
Wrapper around wgpu::Texture.
tonemapping
Tonemapping from an HDR texture to SDR.
transform
Decomposed 3d transform.
tutorial
A tutorial module for the renderling crate.

Macros§

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

Structs§

Context
Contains the adapter, device, queue and RenderTarget.
Frame
Represents the current frame of a render target.
FrameTextureView
A thin wrapper over wgpu::TextureView returned by Frame::view.
RenderTarget
Either a surface or a texture.

Enums§

ContextError