UI 材质
当 Node 的背景色、边框、圆角满足不了你的视觉需求时,UiMaterial 允许你用自定义 WGSL shader 绘制 UI 元素。
UiMaterial 基础
自定义 UI 材质分三步:
- 定义材质结构体,用
#[derive(AsBindGroup, Asset, TypePath)]标注; - 实现
UiMaterialtrait,指定 fragment shader 路径; - 注册
UiMaterialPlugin::<YourMaterial>,用MaterialNode(handle)组件把材质挂到 UI Node 上。
rust
use bevy::prelude::*;
use bevy::render::render_resource::*;
use bevy::shader::ShaderRef;
#[derive(AsBindGroup, Asset, TypePath, Debug, Clone)]
struct MyUiMaterial {
#[uniform(0)]
color: Vec4,
}
impl UiMaterial for MyUiMaterial {
fn fragment_shader() -> ShaderRef {
"shaders/my_ui.wgsl".into()
}
}
fn setup(mut commands: Commands, mut materials: ResMut<Assets<MyUiMaterial>>) {
commands.spawn((
Node { width: px(200), height: px(100), ..default() },
MaterialNode(materials.add(MyUiMaterial {
color: Vec4::new(1.0, 0.5, 0.0, 1.0),
})),
));
}MaterialNode 和普通 Node 共存——你仍然可以设置 border、border_radius、Outline、BoxShadow 等属性。材质只影响背景的绘制方式。
动态更新
材质的 uniform 字段可以在运行时修改。查询 MaterialNode<YourMaterial> 拿到 Handle,再从 Assets<YourMaterial> 资源里取出材质修改即可:
rust
fn animate(
mut materials: ResMut<Assets<MyUiMaterial>>,
q: Query<&MaterialNode<MyUiMaterial>>,
time: Res<Time>,
) {
for handle in &q {
if let Some(mat) = materials.get_mut(handle) {
mat.color.x = time.elapsed_secs().sin() * 0.5 + 0.5;
}
}
}适用场景
UI 材质适合:
- 渐变、条纹、波纹等程序化背景;
- 需要 shader 特效的 UI 元素(进度条填充动画、发光边框);
- 自定义形状的裁切(超出圆角矩形的范围)。
不适合:简单的纯色/图片背景——那些用 BackgroundColor 和 ImageNode 就够了。
本章不深入 shader 编写(那是第 36 章的领地),这里只建立"UI 材质存在"的认知。官方示例 ui/ui_material.rs 有完整可运行的参考。