|
|
@@ -1,42 +1,86 @@
|
|
|
use bevy::{
|
|
|
prelude::*,
|
|
|
- reflect::TypePath,
|
|
|
- render::render_resource::{AsBindGroup, ShaderRef},
|
|
|
+ render::{
|
|
|
+ shader::{Shader, ShaderStage},
|
|
|
+ pipeline::PipelineDescriptor,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
+struct Plane {
|
|
|
+ mesh: Handle<Mesh>,
|
|
|
+ material: Handle<Material>,
|
|
|
+}
|
|
|
+
|
|
|
+fn animate_plane(plane: &mut Plane, time: f32) {
|
|
|
+ // Get the vertices of the plane mesh.
|
|
|
+ let vertices = plane.mesh.get_attribute::<VertexPosition>().unwrap();
|
|
|
+
|
|
|
+ // For each vertex, offset it up and down based on the time.
|
|
|
+ for vertex in vertices {
|
|
|
+ vertex.position.y += (time * 0.1).sin();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update the mesh with the new vertices.
|
|
|
+ plane.mesh.update_attribute(VertexPosition, vertices);
|
|
|
+}
|
|
|
+
|
|
|
+// Fragment shader.
|
|
|
+struct FragmentInput {
|
|
|
+ [[location(0)]] position: Vec2,
|
|
|
+ [[location(1)]] color: Vec3,
|
|
|
+}
|
|
|
+
|
|
|
+#[stage(fragment)]
|
|
|
+fn main([[location(0)]] input: FragmentInput) -> [[location(0)]] Vec4 {
|
|
|
+ return Vec4::new(input.color.x, input.color.y, input.color.z, 1.0);
|
|
|
+}
|
|
|
+
|
|
|
+// Vertex shader.
|
|
|
+struct VertexOutput {
|
|
|
+ [[builtin(position)]] position: Vec4,
|
|
|
+ [[location(0)]] color: Vec3,
|
|
|
+}
|
|
|
+
|
|
|
+#[stage(vertex)]
|
|
|
+fn main([[location(0)]] position: Vec2, [[location(1)]] color: Vec3) -> VertexOutput {
|
|
|
+ return VertexOutput {
|
|
|
+ position: Vec4::new(position.x, position.y, 1.0, 1.0),
|
|
|
+ color,
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
fn main() {
|
|
|
- App::new()
|
|
|
- .add_plugins((DefaultPlugins, MaterialPlugin::<CustomMaterial>::default()))
|
|
|
- .add_systems(Startup, setup)
|
|
|
+ App::build()
|
|
|
+ .add_plugins(DefaultPlugins)
|
|
|
+ .add_startup_system(setup)
|
|
|
+ .add_system(animate_planes)
|
|
|
.run();
|
|
|
}
|
|
|
|
|
|
fn setup(
|
|
|
mut commands: Commands,
|
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
|
- mut materials: ResMut<Assets<CustomMaterial>>,
|
|
|
+ mut shaders: ResMut<Assets<Shader>>,
|
|
|
) {
|
|
|
- // cube
|
|
|
- commands.spawn(MaterialMeshBundle {
|
|
|
- mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
|
|
- transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
|
|
- material: materials.add(CustomMaterial {}),
|
|
|
- ..default()
|
|
|
- });
|
|
|
-
|
|
|
- // camera
|
|
|
- commands.spawn(Camera3dBundle {
|
|
|
- transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
|
|
- ..default()
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
|
|
|
-struct CustomMaterial {}
|
|
|
+ // Create the plane mesh.
|
|
|
+ let plane_mesh = meshes.add(Mesh::from(shape::Plane::default()));
|
|
|
|
|
|
-impl Material for CustomMaterial {
|
|
|
- fn fragment_shader() -> ShaderRef {
|
|
|
- "shaders/animate_shader.wgsl".into()
|
|
|
- }
|
|
|
-}
|
|
|
+ // Create the material.
|
|
|
+ let material = commands
|
|
|
+ .spawn()
|
|
|
+ .insert(material::Material::pipeline(PipelineDescriptor::default()
|
|
|
+ .set_vertex_layout(Vertex::layout())
|
|
|
+ .set_fragment_shader(shaders.add(Shader::from_glsl(ShaderStage::Fragment, include_str!("fragment.wgsl"))))
|
|
|
+ .set_vertex_shader(shaders.add(Shader::from_glsl(ShaderStage::Vertex, include_str!("vertex.wgsl"))))
|
|
|
+ .build()
|
|
|
+ .unwrap()))
|
|
|
+ .id();
|
|
|
|
|
|
+ // Create the plane entity.
|
|
|
+ commands
|
|
|
+ .spawn_bundle(MeshBundle {
|
|
|
+ mesh: plane_mesh,
|
|
|
+ material,
|
|
|
+ transform: Transform::default(),
|
|
|
+ });
|
|
|
+}
|