bevyengine/bevy
Rendering pipeline
How a frame becomes pixels in Bevy. Covers the SubApp boundary, the four render phases, the render graph, phases and items, and where each piece of code lives.
This page brings together bevy_render, bevy_core_pipeline, bevy_pbr, bevy_anti_alias, bevy_post_process, bevy_sprite_render, bevy_ui_render, and bevy_solari.
The four-phase pipeline
graph LR
Main[Main world] -->|Extract| RW[Render world]
RW --> Prepare
Prepare --> Queue
Queue --> Render
Render -->|wgpu submit| GPUEach phase is a system set inside the Render schedule of the RenderApp SubApp. The actual implementation is RenderSet::Extract, RenderSet::Prepare*, RenderSet::Queue*, RenderSet::Render — see crates/bevy_render/src/lib.rs.
Extract
Runs the ExtractSchedule, with the main world available read-only. The job is to copy any data the renderer will need this frame from the main world into the render world. Boilerplate is handled by ExtractComponentPlugin and ExtractResourcePlugin.
After Extract finishes, the main world is unblocked — the next frame's main schedule starts running immediately, in parallel with the rest of the renderer.
Prepare
Runs in the render world. Allocates GPU resources for this frame: per-camera view uniforms, per-light shadow data, per-material bind groups, per-mesh GPU buffers, instance buffers. The pipeline cache is asked to compile any new pipeline specializations.
Queue
Walks the extracted entities for each camera, computes which entities are visible (after frustum culling and RenderLayers), assigns each visible entity a PhaseItem in one of the standard render phases:
- 3D:
Opaque3d,AlphaMask3d,Transparent3d - 2D:
Opaque2d,AlphaMask2d,Transparent2d - Shadow:
Shadow - UI:
TransparentUi - Prepass:
Opaque3dPrepass,AlphaMask3dPrepass
PhaseItems carry a sort key used in the next step.
Render
Walks the render graph node-by-node. Each node has access to the queued phases for its target view and writes commands into the GPU command buffer. After the graph completes, wgpu::Queue::submit is called and the swapchain presents the result.
The render graph
A RenderGraph is a DAG. Nodes implement bevy_render::render_graph::Node and declare named slots. The standard graph (added by Core3dPlugin) contains:
| Node | What it does |
|---|---|
MainPrepassNode |
Depth/normal/motion-vector prepass (when enabled). |
ShadowPassNode |
Per-light shadow map rendering. |
MainOpaquePass3dNode |
Opaque + alpha-mask 3D draws. |
MainTransparentPass3dNode |
Transparent draws. |
BloomNode |
Multi-mip bloom. |
TonemappingNode |
Apply tonemap operator (Reinhard, ACES, AgX, …). |
CASNode / FXAANode / SMAANode / TAANode |
Anti-aliasing. |
UpscalingNode |
Render-target upscale. |
CameraDriverNode |
Final blit/present. |
Plugins like bevy_pbr::PbrPlugin, bevy_sprite_render::SpriteRenderPlugin, bevy_ui_render::UiRenderPlugin, and bevy_anti_alias::* insert their own nodes around these.
Pipelined rendering
sequenceDiagram
participant N as Main frame N+1
participant N0 as Main frame N (just finished)
participant Ext as Extract
participant R as Render frame N
participant GPU
Note over N0,Ext: only synchronization point
N0->>Ext: copy data
Ext->>R: hand off
par main can advance
N->>N: compute frame N+1
and render proceeds
R->>GPU: prepare/queue/render frame N
endpipelined_rendering.rs orchestrates this. The render world owns its own World; the extract step is the only time both worlds are busy at once. After extraction, the renderer runs in parallel with the next frame's main world, doubling effective throughput on render-bound workloads.
Cameras and views
A Camera (with Transform + Projection) defines a view. The camera plugin in bevy_render::camera extracts each camera into a ExtractedCamera plus a per-view uniform buffer (camera matrices, exposure, viewport). RenderLayers filter which entities are extracted per camera.
Multi-camera setups are first-class: multiple cameras can render to the same window with different Viewports, or each can render to its own RenderTarget::Image.
Materials and pipeline specialization
A Material declares a fragment shader, a bind-group layout, and a specialization key. Each (material variant × mesh layout × shader defs) tuple corresponds to one wgpu::RenderPipeline, cached in PipelineCache. Compilation runs asynchronously on a task pool; pipelines that aren't ready yet are simply skipped for the frame and the system retries next frame.
bevy_pbr's StandardMaterial is the canonical implementation. Custom materials are documented in examples/shader/.
Where to start when modifying
| Goal | Crate / file |
|---|---|
| Add a render-graph node | bevy_render — render_graph/node.rs |
| Add a phase item | bevy_render — render_phase/ |
| Custom material | bevy_material + bevy_pbr |
| Post-process effect | bevy_post_process or bevy_core_pipeline |
| Anti-aliasing technique | bevy_anti_alias |
| Custom 2D rendering | bevy_sprite_render |
| Custom UI rendering | bevy_ui_render |
| Ray tracing | bevy_solari |
See also
- Architecture — the full App lifecycle.
bevy_render— the SubApp owner.bevy_core_pipeline— standard nodes and phase items.bevy_pbr— PBR pipeline.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.