要为wgpu着色器提供数组数据,可以使用Bevy PBR库中的Uniform
和Uniforms
类型来定义着色器的uniform变量。
下面是一个使用Bevy PBR和wgpu的例子:
use bevy::prelude::*;
use bevy_pbr::{prelude::*, render_graph::PbrRenderGraphPlugin};
use wgpu::util::DeviceExt;
#[derive(Default)]
struct MyUniforms {
array_data: [f32; 4],
}
fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_plugin(PbrPlugin)
.add_plugin(PbrRenderGraphPlugin)
.add_startup_system(setup.system())
.run();
}
fn setup(
mut commands: Commands,
mut pbr_materials: ResMut>,
mut my_uniforms: ResMut>,
mut meshes: ResMut>,
mut pipelines: ResMut>,
mut shaders: ResMut>,
mut render_graph: ResMut,
mut device: ResMut,
) {
// 创建一个球体
let sphere = meshes.add(Mesh::from(shape::Icosphere::default(), bevy::render::pipeline::PrimitiveTopology::TriangleList));
// 创建着色器
let shader_handle = shaders.add(Shader::from_glsl(
bevy::render::shader::ShaderStage::Vertex,
include_str!("shader.vert"),
));
// 创建着色器的uniform变量
let uniform_handle = my_uniforms.add(MyUniforms {
array_data: [1.0, 2.0, 3.0, 4.0],
});
// 创建管道描述符
let pipeline_handle = pipelines.add(PipelineDescriptor::default_config(ShaderStages {
vertex: shader_handle.clone(),
fragment: Some(shader_handle),
}));
// 创建材质
let material = pbr_materials.add(PbrMaterial {
base_color: Color::WHITE,
..Default::default()
});
// 创建实体并设置材质和管道
commands.spawn_bundle(PbrBundle {
mesh: sphere,
material,
..Default::default()
})
.insert(Uniforms::::new(Some(uniform_handle)))
.insert(PipelineDescriptorHandle::from(pipeline_handle));
// 将着色器的uniform变量绑定到渲染图中
render_graph.add_system_node(
"my_uniforms",
RenderResourcesNode::::new(true),
);
render_graph
.add_node_edge("my_uniforms", bevy::render::render_graph::base::node::MAIN_PASS)
.unwrap();
// 在渲染时将着色器的uniform数据更新到着色器中
render_graph.add_system_node(
"my_uniforms_update",
RenderResourcesNode::::new(false),
);
render_graph
.add_node_edge("my_uniforms_update", "my_uniforms")
.unwrap();
render_graph.add_system_node(
"my_uniforms_update_system",
bevy::render::render_graph::system_node::IntoRenderGraphSystemNode::<
bevy::render::render_graph::node::MainPass,
>::new(MyUniformsUpdateSystem::default()),
);
render_graph
.add_system_node_edge(
"my_uniforms_update_system",
bevy::render::render_graph::base::node::MAIN_PASS,
)
.unwrap();
// 创建一个命令缓冲区来更新着色器的uniform数据
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("uniform_update_encoder"),
});
my_uniforms
.write_buffers(&mut device, &mut encoder)
.expect("Failed to write uniform buffers");
device.get_queue().submit(Some(encoder.finish()));
}
#[derive(Default)]
struct MyUniformsUpdateSystem;
impl> System for MyUniformsUpdateSystem {
fn run(&mut self, mut my_uniforms: ResMut>) {
my_uniforms.get_mut().array_data = [5.0, 6.0, 7.0, 8.0];
}
}
在上述代码中,我们首先定义了一个`MyUniforms