You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Wgpu应用中渲染Egui生成的顶点?适配新版本依赖

在自研Wgpu应用中渲染egui顶点的核心步骤

1. 获取egui的渲染输出数据

每次egui界面更新后,调用egui::Context::tessellate生成渲染所需的原始数据:

let clipped_primitives = ctx.tessellate(shapes);

其中shapes是ctx.run(input_state, |ui| { /* 你的UI代码 */ }).output.shapes。每个ClippedPrimitive包含:

  • primitive:内部是Mesh,存储顶点(pos为屏幕像素坐标、uv、color)和三角形索引。
  • clip_rect:屏幕空间的裁剪矩形,用于后续的视口裁剪。
  • texture_id:对应egui的纹理ID(通常是字体纹理,用于渲染文字)。

2. 同步egui纹理到Wgpu

egui的TextureManager管理所有纹理(包括默认的字体纹理),你需要维护一个TextureId到WgpuTextureView/BindGroup的映射:

  • 初始化时,获取egui默认字体纹理:let font_texture = ctx.texture_manager().texture(&egui::TextureId::Font);,将其像素数据上传到Wgpu的2D纹理(格式用wgpu::TextureFormat::Rgba8UnormSrgb)。
  • 监听egui的纹理更新事件:当ctx.texture_manager().has_changed()返回true时,遍历所有已注册的TextureId,更新对应的Wgpu纹理内容。

3. 坐标转换:屏幕像素→NDC

egui顶点的pos是屏幕左上角为原点的像素坐标,需要转换成Wgpu使用的NDC坐标(范围[-1,1],中心为原点)。通过投影矩阵实现:

let screen_rect = egui::Rect::from_min_max(egui::Pos2::ZERO, egui::Pos2(width as f32, height as f32));
let proj_matrix = egui::emath::projection_matrix(screen_rect, egui::Pos2::ZERO, 1.0);

将这个矩阵作为uniform变量传入顶点着色器,用于转换顶点位置。

4. 编写适配的Wgpu Shader

顶点着色器

struct VertexInput {
    @location(0) pos: vec2<f32>,
    @location(1) uv: vec2<f32>,
    @location(2) color: vec4<f32>,
};

struct VertexOutput {
    @builtin(position) clip_pos: vec4<f32>,
    @location(0) uv: vec2<f32>,
    @location(1) color: vec4<f32>,
};

@group(0) @binding(0)
var<uniform> proj_matrix: mat4x4<f32>;

@vertex
fn vs_main(input: VertexInput) -> VertexOutput {
    var output: VertexOutput;
    output.clip_pos = proj_matrix * vec4<f32>(input.pos, 0.0, 1.0);
    output.uv = input.uv;
    output.color = input.color / 255.0; // 将Color32的0-255转成0-1范围
    return output;
}

片元着色器

@group(1) @binding(0)
var egui_texture: texture_2d<f32>;
@group(1) @binding(1)
var egui_sampler: sampler;

@fragment
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
    let tex_color = textureSample(egui_texture, egui_sampler, input.uv);
    // egui顶点颜色是预乘alpha,直接相乘即可
    return input.color * tex_color;
}

5. 配置Wgpu渲染管道

关键设置:

  • 顶点缓冲布局要匹配egui的Vertex结构(pos: vec2, uv: vec2, color: u32/vec4)。
  • 混合模式使用预乘alpha:
let blend_state = wgpu::BlendState {
    color: wgpu::BlendComponent {
        src_factor: wgpu::BlendFactor::One,
        dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
        operation: wgpu::BlendOperation::Add,
    },
    alpha: wgpu::BlendComponent {
        src_factor: wgpu::BlendFactor::One,
        dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
        operation: wgpu::BlendOperation::Add,
    },
};
  • 启用scissor测试,用于裁剪clip_rect外的像素。

6. 逐Primitive渲染

遍历每个ClippedPrimitive:

  1. 根据clip_rect计算scissor区域,设置到Wgpu的渲染 pass 中。
  2. 根据texture_id绑定对应的纹理BindGroup。
  3. 将当前primitive的顶点和索引数据上传到动态缓冲(或提前准备好的缓冲)。
  4. 调用pass.draw_indexed(),传入索引范围、顶点偏移,完成渲染。

关于egui-wgpu的参考

如果官方egui-wgpu crate的示例过时,直接查看其最新源码中的Renderer实现——它完整封装了上述所有逻辑,你可以提取核心代码适配自己的架构,既保证兼容性,又能保留对渲染流程的控制权。

内容的提问来源于stack exchange,提问作者Redirectk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:11:20