Skip to content

自定义管线搭建

把前面的概念串起来:在渲染子应用中注册系统、分组、建立依赖,构建一个完整的自定义渲染管线。

在 RenderGraph 调度中组织系统

渲染子应用有自己的调度体系,RenderGraph 是其中每帧运行的根调度。往它上面添加系统即可参与渲染:

rust
struct MyGraphPlugin;

impl Plugin for MyGraphPlugin {
    fn build(&self, app: &mut App) {
        let render_app = app.sub_app_mut(RenderApp);

        // 在 RenderGraph 调度中注册系统,使用 .before()/.after() 声明依赖
        render_app.add_systems(
            RenderGraph,
            (node_a, node_b, node_c).chain(), // A → B → C(链式依赖)
        );
    }
}

fn node_a() {
    // 节点 A 的逻辑
}

fn node_b() {
    // 节点 B 的逻辑
}

fn node_c() {
    // 节点 C 的逻辑
}

Listing 37-4:在 RenderGraph 调度中注册系统并声明链式依赖

(node_a, node_b, node_c).chain() 声明 A → B → C 的顺序依赖——旧版渲染图里"画一条边",在 0.19 中就是这个元组调用。

最小自定义管线

下面的示例把所有概念组合在一起:在 RenderStartup 初始化资源、在 ExtractSchedule 提取数据、在 Render 的各阶段执行系统、在 RenderGraph 调度注册自定义标签分组的系统。

rust
struct CustomRenderPlugin;

impl Plugin for CustomRenderPlugin {
    fn build(&self, app: &mut App) {
        let render_app = app.sub_app_mut(RenderApp);

        // 1. 在 RenderStartup 中初始化渲染资源
        render_app.add_systems(RenderStartup, init_frame_counter);

        // 2. 在 ExtractSchedule 中提取主世界数据
        render_app.add_systems(ExtractSchedule, extract_time);

        // 3. 在 Render 调度的各阶段注册系统
        render_app.add_systems(
            Render,
            prepare_counter
                .in_set(RenderSystems::Prepare)
                .before(RenderSystems::Render),
        );

        // 4. 在 RenderGraph 调度中注册系统,并用自定义标签分组
        render_app.add_systems(
            RenderGraph,
            log_frame_in_graph.in_set(CustomRenderLabels::FrameLog),
        );
    }
}
rust
/// 自定义渲染标签:0.19 中渲染图标签就是 SystemSet
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
enum CustomRenderLabels {
    /// 帧日志系统
    FrameLog,
}
rust
#[derive(Resource, Default)]
struct FrameCounter {
    frames: u64,
}

fn init_frame_counter(mut commands: Commands) {
    commands.insert_resource(FrameCounter::default());
}

fn extract_time(mut counter: ResMut<FrameCounter>) {
    counter.frames += 1;
    if counter.frames % 300 == 0 {
        info!("渲染管线已运行 {} 帧", counter.frames);
    }
}

fn prepare_counter(counter: Res<FrameCounter>) {
    let _ = counter.frames;
}
rust
fn log_frame_in_graph(mut counter: ResMut<FrameCounter>) {
    counter.frames = counter.frames.wrapping_add(1);
}

Listing 37-5:最小自定义渲染管线——插件、标签、资源与节点

标签是 SystemSet(第 6 章的集合机制,渲染世界同样适用)。CustomRenderLabels::FrameLog 把帧日志系统归组,方便统一排序。

运行方式

console
cargo run -p ch37-render-arch

每 300 帧会输出一条日志,表明自定义渲染管线在正常运行。