Rust 3D渲染引擎re_renderer的使用,高性能实时渲染与图形处理库

Rust 3D渲染引擎re_renderer的使用,高性能实时渲染与图形处理库

re_renderer是基于wgpu的自定义渲染器,专为re_viewer的需求而定制。尽管如此,它可以独立使用,并附带自己的示例!

一些关键特性:

  • 线条和点等可视化的关键基元是一等公民
  • 构建时考虑了多个独立视图/摄像机
  • WebGL兼容的质量层允许在没有WebGPU支持的浏览器中使用
  • 热着色器重新加载
  • ……还有更多功能即将推出!

目标与理念:

  • 处理完全动态的数据
    • 假设大多数数据可能每帧都会变化!
  • 自动资源重用和缓存
  • 尽可能延迟加载以获得最佳启动性能
  • 在桌面和Web上都能良好运行
  • 不依赖re_viewer或Rerun块存储库

调试

在浏览器中调试

使用--enable-dawn-features=dump_shaders,disable_symbol_renaming启动Chrome。

着色器

迭代

在调试模式下,如果从Rerun工作区构建,着色器会实时重新加载。如果在实时重新加载期间发生故障,会记录错误并保留先前的着色器。

检查最终源代码

如果设置了RERUN_WGSL_SHADER_DUMP_PATH,所有准备好的拼接(导入解析)和修补的wgsl着色器将被写入指定目录。

通常您也对Naga翻译的着色器感兴趣。这可以从命令行轻松完成:

cargo install naga-cli --all-features

将wgsl片段着色器翻译为WebGL上使用的GL的示例:

naga ./wgsl_dump/rectangle_fs.wgsl ./wgsl_dump/rectangle_fs.frag --entry-point fs_main --profile es300

将wgsl顶点着色器翻译为WebGL上使用的GL的示例:

naga ./wgsl_dump/rectangle_vs.wgsl ./wgsl_dump/rectangle_vs.vert --entry-point vs_main --profile es300

请注意,wgsl中的单个着色器入口点映射到单个frag/vert文件!

将wgsl翻译为MacOS上使用的MSL的示例。 请注意,单个metal文件映射到单个wgsl文件。

naga ./wgsl_dump/rectangle_fs.wgsl ./wgsl_dump/rectangle_fs.metal

完整示例代码

use re_renderer::{
    renderer::{
        ColormappedTexture, GenericSkyboxShader, LineDrawable, LineStripFlags, PointDrawable,
        RenderContext,
    },
    view_builder::ViewBuilder,
    wgpu_resources::GpuTexture,
    Renderer,
};
use winit::{
    event::{Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    window::WindowBuilder,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建事件循环和窗口
    let event_loop = EventLoop::new();
    let window = WindowBuilder::new()
        .with_title("Rerun Renderer Example")
        .build(&event_loop)?;

    // 初始化渲染器
    let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::default());
    let surface = unsafe { instance.create_surface(&window) }?;
    
    let mut renderer = Renderer::new(
        RenderContext::new(
            &instance,
            &surface,
            wgpu::Limits::default(),
            wgpu::Features::empty(),
        )
        .await?,
    );

    let mut view_builder = ViewBuilder::new();

    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Poll;

        match event {
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                ..
            } => {
                *control_flow = ControlFlow::Exit;
            }
            Event::RedrawRequested(_) => {
                // 开始构建视图
                view_builder
                    .setup_view("main", &window)
                    .clear_color(wgpu::Color::BLACK);

                // 创建一些示例几何体
                let points = vec![
                    glam::Vec3::new(0.0, 0.0, 0.0),
                    glam::Vec3::new(1.0, 0.0, 0.0),
                    glam::Vec3::new(0.0, 1.0, 0.0),
                ];

                let lines = vec![
                    glam::Vec3::new(-1.0, -1.0, 0.0),
                    glam::Vec3::new(1.0, -1.0, 0.0),
                    glam::Vec3::new(0.0, 1.0, 0.0),
                    glam::Vec3::new(-1.0, -1.0, 0.0), // 闭合三角形
                ];

                // 添加点到渲染器
                let point_drawable = PointDrawable::new(points)
                    .with_colors(vec![
                        glam::Vec4::new(1.0, 0.0, 0.0, 1.0), // 红色
                        glam::Vec4::new(0.0, 1.0, 0.0, 1.0), // 绿色
                        glam::Vec4::new(0.0, 0.0, 1.0, 1.0), // 蓝色
                    ])
                    .with_radii(vec![10.0, 15.0, 20.0]);

                renderer.add_drawable(point_drawable);

                // 添加线到渲染器
                let line_drawable = LineDrawable::new(lines)
                    .with_colors(vec![
                        glam::Vec4::new(1.0, 1.0, 0.0, 1.0), // 黄色
                        glam::Vec4::new(1.0, 0.0, 1.0, 1.0), // 紫色
                        glam::Vec4::new(0.0, 1.0, 1.0, 1.0), // 青色
                        glam::Vec4::new(1.0, 1.0, 0.0, 1.0), // 黄色
                    ])
                    .with_strip_flags(LineStripFlags::CLOSED);

                renderer.add_drawable(line_drawable);

                // 渲染场景
                if let Err(e) = renderer.render(&mut view_builder) {
                    eprintln!("渲染错误: {}", e);
                }
            }
            Event::MainEventsCleared => {
                window.request_redraw();
            }
            _ => {}
        }
    });
}

要运行此示例,请将以下内容添加到您的Cargo.toml:

[dependencies]
re_renderer = "0.24.1"
winit = "0.28"
tokio = { version = "1.0", features = ["full"] }

这个示例展示了如何使用re_renderer创建一个简单的3D场景,包含彩色点和线条。渲染器会自动处理资源管理和优化,为您提供高性能的实时渲染体验。


1 回复

re_renderer:Rust高性能3D渲染引擎

简介

re_renderer是一个基于Rust语言开发的高性能3D渲染引擎,专注于实时渲染和图形处理。该库提供了现代化的图形API抽象,支持跨平台部署,并针对数据驱动渲染进行了优化。

主要特性

  • 高性能实时渲染管线
  • Vulkan/Metal/DX12后端支持
  • 基于ECS的数据驱动架构
  • 物理基于渲染(PBR)材质系统
  • 多线程渲染命令处理
  • 自动资源管理和内存分配

基本使用方法

添加依赖

[dependencies]
re_renderer = "0.8"

初始化引擎

use re_renderer::{
    Renderer, 
    RendererCreationError,
    RendererSettings
};

fn main() -> Result<(), RendererCreationError> {
    let settings = RendererSettings {
        vsync: true,
        msaa_samples: 4,
        ..Default::default()
    };
    
    let mut renderer = Renderer::new(settings)?;
    Ok(())
}

创建简单场景

use re_renderer::{
    Mesh, Material, Camera,
    renderer::MeshDrawData
};

// 创建网格数据
let vertices = vec![
    // 顶点位置和法线数据
    // ...
];

let indices = vec![0, 1, 2]; // 三角形索引

let mesh = Mesh::from_vertices(vertices, indices);

// 创建材质
let material = Material::pbr()
    .albedo([1.0, 0.0, 0.0, 1.0]) // 红色材质
    .metallic(0.2)
    .roughness(0.8);

// 设置相机
let camera = Camera::perspective(
    [0.0, 0.0, 5.0],  // 位置
    [0.0, 0.0, 0.0],  // 目标
    [0.0, 1.0, 0.0],  // 上向量
    45.0,             // 视野
    0.1,              // 近平面
    100.0             // 远平面
);

渲染循环示例

use re_renderer::{FrameContext, RenderGraph};

fn render_frame(renderer: &mut Renderer, camera: &Camera) {
    let mut frame_ctx = FrameContext::new();
    
    // 构建渲染图
    let mut render_graph = RenderGraph::new();
    
    // 添加主渲染通道
    render_graph.add_render_pass("main", |pass_builder| {
        pass_builder
            .clear_color([0.1, 0.2, 0.3, 1.0])
            .clear_depth(1.0)
            .camera(camera.clone())
    });
    
    // 执行渲染
    renderer.execute_frame(&mut frame_ctx, render_graph);
}

高级功能示例

自定义着色器

use re_renderer::shader::ShaderModule;

// 加载GLSL着色器
let vertex_shader = ShaderModule::from_glsl(
    include_str!("shaders/triangle.vert"),
    re_renderer::shader::ShaderStage::Vertex
);

let fragment_shader = ShaderModule::from_glsl(
    include_str!("shaders/triangle.frag"),
    re_renderer::shader::ShaderStage::Fragment
);

多线程渲染

use std::sync::Arc;
use re_renderer::renderer::ParallelRenderContext;

// 在多线程环境中准备渲染数据
let render_context = Arc::new(ParallelRenderContext::new());

// 在不同线程中准备渲染对象
rayon::scope(|s| {
    s.spawn(|_| {
        // 准备网格数据
        let mesh_data = prepare_mesh_data();
        render_context.add_mesh(mesh_data);
    });
    
    s.spawn(|_| {
        // 准备材质数据
        let material_data = prepare_material_data();
        render_context.add_material(material_data);
    });
});

性能优化提示

  1. 使用实例化渲染处理大量相似对象
  2. 利用渲染图的自动批处理和排序
  3. 合理使用多线程资源准备
  4. 选择适当的纹理压缩格式
  5. 使用GPU驱动的场景剔除技术

re_renderer提供了丰富的工具和API来构建高性能的3D应用程序,同时保持了Rust语言的安全性和并发优势。

完整示例demo

use re_renderer::{
    Renderer, RendererCreationError, RendererSettings,
    Mesh, Material, Camera, FrameContext, RenderGraph
};
use std::f32::consts::PI;

fn main() -> Result<(), RendererCreationError> {
    // 初始化渲染器
    let settings = RendererSettings {
        vsync: true,
        msaa_samples: 4,
        ..Default::default()
    };
    
    let mut renderer = Renderer::new(settings)?;
    
    // 创建三角形网格
    let vertices = vec![
        // 位置坐标 (x, y, z) 和法线 (nx, ny, nz)
        [-0.5, -0.5, 0.0, 0.0, 0.0, 1.0], // 左下顶点
        [0.5, -0.5, 0.0, 0.0, 0.0, 1.0],  // 右下顶点
        [0.0, 0.5, 0.0, 0.0, 0.0, 1.0],   // 上顶点
    ];
    
    let indices = vec![0, 1, 2]; // 三角形索引
    
    let mesh = Mesh::from_vertices(vertices, indices);
    
    // 创建PBR材质
    let material = Material::pbr()
        .albedo([1.0, 0.0, 0.0, 1.0]) // 红色材质
        .metallic(0.2)
        .roughness(0.8);
    
    // 设置相机
    let mut camera = Camera::perspective(
        [0.0, 0.0, 5.0],  // 位置
        [0.0, 0.0, 0.0],  // 目标
        [0.0, 1.0, 0.0],  // 上向量
        45.0,             // 视野
        0.1,              // 近平面
        100.0             // 远平面
    );
    
    // 简单的渲染循环模拟
    for frame in 0..60 {
        // 每帧更新相机位置(简单的旋转)
        let angle = (frame as f32 / 60.0) * 2.0 * PI;
        camera.position = [angle.sin() * 5.0, 0.0, angle.cos() * 5.0];
        
        render_frame(&mut renderer, &camera, &mesh, &material);
    }
    
    Ok(())
}

fn render_frame(renderer: &mut Renderer, camera: &Camera, mesh: &Mesh, material: &Material) {
    let mut frame_ctx = FrameContext::new();
    
    // 构建渲染图
    let mut render_graph = RenderGraph::new();
    
    // 添加主渲染通道
    render_graph.add_render_pass("main", |pass_builder| {
        pass_builder
            .clear_color([0.1, 0.2, 0.3, 1.0]) // 深蓝色背景
            .clear_depth(1.0)
            .camera(camera.clone())
            // 这里可以添加网格和材质的绘制命令
    });
    
    // 执行渲染
    renderer.execute_frame(&mut frame_ctx, render_graph);
}

这个完整示例展示了如何使用re_renderer创建一个简单的3D应用程序,包括初始化渲染器、创建网格和材质、设置相机以及实现基本的渲染循环。

回到顶部