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 mut stage: Stage = ctx.new_stage();
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
Hybrid
s and
HybridArray
s.
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:
§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§
- Texture atlas.
- Helpers for bitwise operations.
- Physically based bloom.
- Camera projection, view and utilities.
- Color utils.
- Convolution shaders.
- Render pipelines and layouts for creating cubemaps.
- Resources for image based lighting.
- Mathematical helper types and functions.
- “Physically based” types and functions.
- Skybox shaders and CPU code.
- GPU and CPU slab allocation.
- GPU staging area.
- Wrapper around
wgpu::Texture
. - Tonemapping from an HDR texture to SDR.
- Decomposed 3d transform.
- A tutorial module for the renderling crate.
Macros§
- A wrapper around
std::println
that is a noop on the GPU.
Structs§
- Contains the adapter, device, queue and
RenderTarget
. - Represents the current frame of a render target.
- A thin wrapper over
wgpu::TextureView
returned byFrame::view
. - Either a surface or a texture.