Expand description
§banished-gfx
Rendering code that the game (apps/game) and the viewer (apps/viewer) share. It uses
wgpu, so it runs on Vulkan, Metal, DirectX 12, OpenGL, and in browsers on
WebGPU or WebGL 2.
| Part | What it does |
|---|---|
UiRenderer | Draws the quads of banished-ui in one alpha-blended pipeline, in batches split by texture and clip rectangle |
upload_image, upload_rgba, upload_cube, … | Upload the game’s textures (ImageBuffer) to the GPU, with their mip levels |
decode_levels | Decode every level of a texture to RGBA8, for GPUs without BC texture support |
material | Which ported shader a model’s material uses (MaterialKind), and the atlas of citizens’ outfits |
model | The draw ranges of a mesh: which material, shader, textures and node transform each range uses |
skin | GPU skinning: the vertex layout of skinned meshes, the bone palette and its WGSL |
The game’s own scene renderer (terrain, water, models, shadows, particles) is in apps/game. This
crate holds only what both programs need.
§Use it
[dependencies]
banished-gfx = { path = "crates/gfx" }
banished-ui = { path = "crates/ui" }
banished-formats = { path = "crates/formats" }
wgpu = "30"§Draw the interface
Create the renderer once, with the format of your colour and depth targets. Each frame, pass the
quads from Ui::draw. The renderer uploads the sprite sheets that the quads use the first time
it sees them.
use banished_gfx::UiRenderer;
use banished_ui::{NodeId, Ui};
fn draw_ui<'p>(
renderer: &'p mut UiRenderer,
device: &wgpu::Device,
queue: &wgpu::Queue,
pass: &mut wgpu::RenderPass<'p>,
ui: &Ui,
root: NodeId,
size: (u32, u32),
) {
let quads = ui.draw(root);
renderer.draw(device, queue, pass, ui, &quads, size);
}
fn make(device: &wgpu::Device) -> UiRenderer {
UiRenderer::new(device, wgpu::TextureFormat::Bgra8UnormSrgb, wgpu::TextureFormat::Depth32Float)
}set_external(device, id, view) registers an application texture for quads with
Texture::External(id), for example a preview picture in a dialog. set_time drives the
animated interface materials.
§Upload a texture
use banished_formats::pkg::Archive;
use banished_formats::types::image_buffer;
fn texture(
device: &wgpu::Device,
queue: &wgpu::Queue,
archive: &Archive,
reference: &str,
) -> Option<wgpu::TextureView> {
let image = image_buffer(&archive.read_ref(reference).ok()?).ok()?;
banished_gfx::upload_image(device, queue, reference, &image)
}upload_image decodes every mip level to RGBA8 on the CPU (decode_levels), because WebGL 2
often has no support for BC-compressed textures, and uploads the result as an sRGB texture.
upload_image_linear uploads without sRGB conversion; upload_cube uploads a cube map.
§Rules for code in this crate
- It must work on WebGL 2: no storage buffers in vertex shaders, no base-vertex draws, the
downlevel_webgl2_defaultslimits. - In WGSL, do every texture sample before any
discard.
Port a shader explains these rules.
§The API
The full API documentation is at https://tanepiper.github.io/unbanished/api/banished_gfx/index.html.
Modules§
- material
- Model material classification and the character outfit atlas, shared by the viewer and the game so both draw a material the same way.
- model
- CPU-side description of a
GraphicsMesh’s draw ranges, shared by the viewer and the game: which material each range uses, which shader kind that is, its textures and its rigid node transform. GPU upload and skinning strategy stay with each app. - skin
- GPU skinning shared by the viewer and the game: the
ModelSkinLayoutvertex attributes, the bone palette uniform and its WGSL. The original’sNormalSkin_*vsprograms blend four bones from a palette of transforms (tc_transform,c41, four rows per bone).
Structs§
- UiRenderer
- Draws the quads of
banished-uiwith wgpu: one alpha-blended pipeline (and one for the logo material), in batches split by texture and clip rectangle. It uploads each sprite sheet the first time a quad uses it.
Functions§
- decode_
levels - Decode an
ImageBufferinto RGBA8 levels:faces × mips(face-major, as stored). - upload_
cube - Upload a cube-map
ImageBuffer(6 faces, D3D order +X −X +Y −Y +Z −Z) as a cube view. - upload_
image - Decode and upload an
ImageBufferwith all its mip levels (sRGB). - upload_
image_ linear - Upload a 2D
ImageBuffer(all mips) as linear RGBA8, the way the D3D9 renderer samples it. - upload_
rgba - Upload RGBA8 mip levels as an sRGB texture.
- upload_
rgba_ as - Upload 4-byte-per-texel mip levels in
format.