ferrous_renderer documentation¶
ferrous_renderer is the GPU rendering layer of FerrousEngine. It
wraps wgpu behind a high-level, modular interface that can drive both
a game window and render to an off-screen texture simultaneously.
The crate is intentionally decoupled from windowing: it receives an
EngineContext (device + queue) and a target surface and handles
everything else internally.
Documentation map¶
docs/
├── README.md # this file – overview and quick start
├── architecture.md # module tree, data-flow, FramePacket lifecycle
├── render_pass.md # RenderPass trait – the primary extension point
├── camera.md # GpuCamera, OrbitState, Controller configuration
├── geometry.md # Vertex, Mesh, built-in primitives, custom geometry
├── materials.md # material & texture system (slots, registry, shaders)
├── render_target.md # off-screen rendering, MSAA, pixel readback
├── gizmo.md # GizmoDraw, GizmoPipeline, execute_gizmo_pass(), GizmoStyle
└── extending/
├── custom_pass.md # step-by-step guide to writing a custom raster pass
├── new_pipeline.md # adding a new wgpu render pipeline
├── compute_pipeline.md # adding a compute shader pass (raymarching, particles, …)
└── world_sync.md # hooking new scene element types into sync_world
## Quick start
Add the crate to your workspace:
```toml
[dependencies]
ferrous_renderer = { path = "../ferrous_renderer" }
Create a Renderer in your application setup and drive it each frame:
use ferrous_renderer::{Renderer, FramePacket, Viewport};
// --- setup (once) ---
let mut renderer = Renderer::new(&ctx, surface_width, surface_height);
// Optional: upload a font atlas for text rendering
renderer.set_font_atlas(&ctx, &atlas_bytes, atlas_width, atlas_height);
// --- per-frame ---
let output = surface.get_current_texture()?;
let view = output.texture.create_view(&Default::default());
renderer.handle_input(&input_state, delta_time);
renderer.sync_world(&world, &ctx);
renderer.render_to_view(&ctx, &view);
output.present();
Architecture at a glance¶
The renderer is structured around a render graph consisting of ordered passes. Each frame follows this contract:
build_packet— converts the live scene into aFramePacket(pure CPU data).prepare— every activeRenderPassuploads GPU data it needs (uniforms, staging buffers, …).execute— aCommandEncoderis recorded; each pass appends its draw calls.queue.submit— the finished command buffer is submitted.
The default pass list is:
| Order | Pass | Responsibility |
|---|---|---|
| 0 | WorldPass |
clears the frame, draws 3-D scene objects |
| 1 | UiPass |
composites the GUI and text layers on top |
Compute workloads are added manually via Renderer::add_pass using
ComputePass. Register them before WorldPass when their output is
consumed by raster passes in the same frame.
You can replace or extend this list with Renderer::add_pass /
Renderer::clear_passes. See render_pass.md for full details.
Key public types¶
| Type | Where defined | Purpose |
|---|---|---|
Renderer |
lib.rs |
top-level entry point |
RenderPass |
graph/pass_trait.rs |
trait for custom passes (raster and compute) |
FramePacket |
graph/frame_packet.rs |
per-frame CPU data bundle |
Viewport |
graph/frame_packet.rs |
scissor/viewport rectangle |
Mesh |
geometry/mesh.rs |
GPU vertex + index buffers |
Vertex |
geometry/vertex.rs |
interleaved position + colour |
Camera |
(re-export from ferrous_core) | view + projection state |
Controller |
(re-export from ferrous_core) | key bindings + motion config |
GpuCamera |
camera/uniform.rs |
GPU-side camera uniform |
RenderTarget |
render_target/target.rs |
colour + depth target, MSAA-aware |
ComputePipeline |
pipeline/compute.rs |
generic wgpu compute pipeline wrapper |
ComputePass |
passes/compute_pass.rs |
compute shader dispatch via the render graph |
RenderObject |
scene/object.rs |
per-instance GPU data |
GizmoDraw |
scene/gizmo.rs |
per-frame gizmo draw descriptor (transform + style) |
GizmoPipeline |
pipeline/gizmo.rs |
LineList pipeline, depth Always, no depth write |
GizmoStyle |
(re-export from ferrous_core) | full visual config for a gizmo instance |
Feature highlights¶
- Render to texture —
Renderer::render_to_targetwrites into the internalRenderTargetinstead of a swap-chain view. The resolved single-sample texture is accessible viarenderer.render_target().color_texture()for use as aGuiQuadbackground or for CPU readback. - MSAA x4 — depth and colour targets are created with four samples by default; a resolve pass writes the final image to a single-sample texture.
- Configurable camera — speed, mouse sensitivity, orbit distance,
and arbitrary key bindings are all runtime-configurable. See
camera.mdfor details. - Custom render passes — implement the
RenderPasstrait to inject any GPU work (shadow maps, post-processing, outlines, …) into the frame. Seeextending/custom_pass.mdfor a worked example.
Further reading¶
architecture.md— understand the complete data flow before writing any extensions.render_pass.md— full trait reference and contract.camera.md— configure movement speed, key mappings, and sensitivity.geometry.md— create meshes from code or load them from assets.render_target.md— off-screen rendering and MSAA details.gizmo.md— GizmoDraw, GizmoPipeline, vertex generation, and GizmoStyle reference.extending/— practical guides for common extension scenarios.