mirror of
https://github.com/bevyengine/bevy
synced 2024-11-24 13:43:04 +00:00
refactor app startup. AppBuilder. clean up examples
This commit is contained in:
parent
aeeb85b7b0
commit
55c50f7185
16 changed files with 633 additions and 422 deletions
7
examples/empty.rs
Normal file
7
examples/empty.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use bevy::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
AppBuilder::new()
|
||||||
|
.add_defaults()
|
||||||
|
.run();
|
||||||
|
}
|
212
examples/instancing.rs
Normal file
212
examples/instancing.rs
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
use bevy::*;
|
||||||
|
use bevy::{render::*, asset::{Asset, AssetStorage, Handle}, math::{Mat4, Vec3}, Schedulable};
|
||||||
|
use rand::{rngs::StdRng, Rng, SeedableRng, random};
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
struct Person;
|
||||||
|
|
||||||
|
struct Velocity {
|
||||||
|
pub value: math::Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NavigationPoint {
|
||||||
|
pub target: math::Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Wander {
|
||||||
|
pub duration_bounds: math::Vec2,
|
||||||
|
pub distance_bounds: math::Vec2,
|
||||||
|
pub duration: f32,
|
||||||
|
pub elapsed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
AppBuilder::new()
|
||||||
|
.add_defaults()
|
||||||
|
.setup(&setup)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
|
||||||
|
let cube = Mesh::load(MeshType::Cube);
|
||||||
|
let cube_handle = {
|
||||||
|
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh, MeshType>>().unwrap();
|
||||||
|
mesh_storage.add(cube, "cube")
|
||||||
|
};
|
||||||
|
|
||||||
|
let transform_system_bundle = transform_system_bundle::build(world);
|
||||||
|
scheduler.add_systems(AppStage::Update, transform_system_bundle);
|
||||||
|
scheduler.add_system(AppStage::Update, build_wander_system());
|
||||||
|
scheduler.add_system(AppStage::Update, build_navigate_system());
|
||||||
|
scheduler.add_system(AppStage::Update, build_move_system());
|
||||||
|
scheduler.add_system(AppStage::Update, build_print_status_system());
|
||||||
|
|
||||||
|
world.insert((), vec![
|
||||||
|
// lights
|
||||||
|
(
|
||||||
|
Light {
|
||||||
|
color: wgpu::Color {
|
||||||
|
r: 0.8,
|
||||||
|
g: 0.8,
|
||||||
|
b: 0.5,
|
||||||
|
a: 1.0,
|
||||||
|
},
|
||||||
|
fov: f32::to_radians(60.0),
|
||||||
|
depth: 0.1 .. 50.0,
|
||||||
|
target_view: None,
|
||||||
|
},
|
||||||
|
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0)),
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
Translation::new(4.0, -4.0, 5.0),
|
||||||
|
Rotation::from_euler_angles(0.0, 0.0, 0.0)
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
world.insert((), vec![
|
||||||
|
// camera
|
||||||
|
(
|
||||||
|
Camera::new(CameraType::Projection {
|
||||||
|
fov: std::f32::consts::PI / 4.0,
|
||||||
|
near: 1.0,
|
||||||
|
far: 1000.0,
|
||||||
|
aspect_ratio: 1.0,
|
||||||
|
}),
|
||||||
|
ActiveCamera,
|
||||||
|
LocalToWorld(Mat4::look_at_rh(
|
||||||
|
Vec3::new(6.0, -40.0, 20.0),
|
||||||
|
Vec3::new(0.0, 0.0, 0.0),
|
||||||
|
Vec3::new(0.0, 0.0, 1.0),)),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
let mut rng = StdRng::from_entropy();
|
||||||
|
for _ in 0 .. 70000 {
|
||||||
|
create_person(world, cube_handle.clone(),
|
||||||
|
Translation::new(rng.gen_range(-50.0, 50.0), 0.0, rng.gen_range(-50.0, 50.0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_wander_system() -> Box<dyn Schedulable> {
|
||||||
|
let mut rng = StdRng::from_entropy();
|
||||||
|
|
||||||
|
SystemBuilder::new("Wander")
|
||||||
|
.read_resource::<Time>()
|
||||||
|
.with_query(<(
|
||||||
|
Read<Person>,
|
||||||
|
Read<Translation>,
|
||||||
|
Write<Wander>,
|
||||||
|
Write<NavigationPoint>,
|
||||||
|
)>::query())
|
||||||
|
.build(move |
|
||||||
|
_, world,
|
||||||
|
time ,
|
||||||
|
person_query| {
|
||||||
|
for (_, translation, mut wander, mut navigation_point) in person_query.iter(world) {
|
||||||
|
wander.elapsed += time.delta_seconds;
|
||||||
|
if wander.elapsed >= wander.duration {
|
||||||
|
let direction = math::vec3(
|
||||||
|
rng.gen_range(-1.0, 1.0),
|
||||||
|
rng.gen_range(-1.0, 1.0),
|
||||||
|
rng.gen_range(0.0, 0.001),
|
||||||
|
).normalize();
|
||||||
|
let distance = rng.gen_range(wander.distance_bounds.x(), wander.distance_bounds.y());
|
||||||
|
navigation_point.target = translation.0 + direction * distance;
|
||||||
|
wander.elapsed = 0.0;
|
||||||
|
wander.duration = rng.gen_range(wander.duration_bounds.x(), wander.duration_bounds.y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_navigate_system() -> Box<dyn Schedulable> {
|
||||||
|
SystemBuilder::new("Navigate")
|
||||||
|
.with_query(<(
|
||||||
|
Read<Person>,
|
||||||
|
Write<Translation>,
|
||||||
|
Write<Velocity>,
|
||||||
|
Write<NavigationPoint>,
|
||||||
|
)>::query())
|
||||||
|
.build(move |
|
||||||
|
_, world,
|
||||||
|
_, person_query| {
|
||||||
|
for (_, translation, mut velocity, navigation_point) in person_query.iter(world) {
|
||||||
|
let distance = navigation_point.target - translation.0;
|
||||||
|
if distance.length() > 0.01 {
|
||||||
|
let direction = distance.normalize();
|
||||||
|
velocity.value = direction * 2.0;
|
||||||
|
} else {
|
||||||
|
velocity.value = math::vec3(0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_move_system() -> Box<dyn Schedulable> {
|
||||||
|
SystemBuilder::new("Move")
|
||||||
|
.read_resource::<Time>()
|
||||||
|
.with_query(<(
|
||||||
|
Write<Translation>,
|
||||||
|
Read<Velocity>,
|
||||||
|
)>::query())
|
||||||
|
.build(move |_, world, time , person_query| {
|
||||||
|
for (mut translation, velocity) in person_query.iter(world) {
|
||||||
|
translation.0 += velocity.value * time.delta_seconds;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_print_status_system() -> Box<dyn Schedulable> {
|
||||||
|
let mut elapsed = 0.0;
|
||||||
|
let mut frame_time_total = 0.0;
|
||||||
|
let mut frame_time_count = 0;
|
||||||
|
let frame_time_max = 10;
|
||||||
|
let mut frame_time_values = VecDeque::new();
|
||||||
|
SystemBuilder::new("PrintStatus")
|
||||||
|
.read_resource::<Time>()
|
||||||
|
.with_query(<(
|
||||||
|
Read<Person>,
|
||||||
|
)>::query())
|
||||||
|
.build(move |_, world, time , person_query| {
|
||||||
|
elapsed += time.delta_seconds;
|
||||||
|
frame_time_values.push_front(time.delta_seconds);
|
||||||
|
frame_time_total += time.delta_seconds;
|
||||||
|
frame_time_count += 1;
|
||||||
|
if frame_time_count > frame_time_max {
|
||||||
|
frame_time_count = frame_time_max;
|
||||||
|
frame_time_total -= frame_time_values.pop_back().unwrap();
|
||||||
|
}
|
||||||
|
if elapsed > 1.0 {
|
||||||
|
// println!("fps: {}", if time.delta_seconds == 0.0 { 0.0 } else { 1.0 / time.delta_seconds });
|
||||||
|
if frame_time_count > 0 && frame_time_total > 0.0 {
|
||||||
|
println!("fps: {}", 1.0 / (frame_time_total / frame_time_count as f32))
|
||||||
|
}
|
||||||
|
println!("peeps: {}", person_query.iter(world).count());
|
||||||
|
elapsed = 0.0;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_person(world: &mut World, mesh_handle: Handle<Mesh>, translation: Translation) {
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
Person{},
|
||||||
|
Wander {
|
||||||
|
duration_bounds: math::vec2(3.0, 10.0),
|
||||||
|
distance_bounds: math::vec2(-50.0, 50.0),
|
||||||
|
elapsed: 0.0,
|
||||||
|
duration: 0.0,
|
||||||
|
},
|
||||||
|
NavigationPoint {
|
||||||
|
target: math::vec3(0.0, 0.0, 0.0),
|
||||||
|
},
|
||||||
|
Velocity {
|
||||||
|
value: math::vec3(0.0, 0.0, 0.0),
|
||||||
|
},
|
||||||
|
Instanced,
|
||||||
|
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0) * random::<f32>()),
|
||||||
|
mesh_handle,
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
translation
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
|
@ -1,11 +1,8 @@
|
||||||
use bevy::*;
|
use bevy::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// let universe = Universe::new();
|
|
||||||
// let world = universe.create_world();
|
|
||||||
// let scheduler = SystemScheduler::<ApplicationStage>::new();
|
|
||||||
// asset::load_gltf(get_path("examples/assets/Box.gltf").to_str().unwrap()).unwrap();
|
|
||||||
asset::load_gltf("examples/assets/Box.gltf").unwrap();
|
asset::load_gltf("examples/assets/Box.gltf").unwrap();
|
||||||
|
AppBuilder::new()
|
||||||
// Application::run(universe, world, scheduler);
|
.add_defaults()
|
||||||
|
.run();
|
||||||
}
|
}
|
110
examples/parenting.rs
Normal file
110
examples/parenting.rs
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
use bevy::{*, render::*, asset::{Asset, AssetStorage}, math::{Mat4, Quat, Vec3}, Schedulable, Parent};
|
||||||
|
|
||||||
|
struct Rotator;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
AppBuilder::new()
|
||||||
|
.add_defaults()
|
||||||
|
.setup(&setup)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_rotator_system() -> Box<dyn Schedulable> {
|
||||||
|
SystemBuilder::new("Rotator")
|
||||||
|
.read_resource::<Time>()
|
||||||
|
.with_query(<(
|
||||||
|
Write<Rotator>,
|
||||||
|
Write<Rotation>,
|
||||||
|
)>::query())
|
||||||
|
.build(move |_, world, time , light_query| {
|
||||||
|
for (_, mut rotation) in light_query.iter(world) {
|
||||||
|
rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
|
||||||
|
let cube = Mesh::load(MeshType::Cube);
|
||||||
|
let plane = Mesh::load(MeshType::Plane{ size: 10.0 });
|
||||||
|
|
||||||
|
let (cube_handle, plane_handle) = {
|
||||||
|
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh, MeshType>>().unwrap();
|
||||||
|
(mesh_storage.add(cube, "cube"), mesh_storage.add(plane, "plane"))
|
||||||
|
};
|
||||||
|
|
||||||
|
let transform_system_bundle = transform_system_bundle::build(world);
|
||||||
|
scheduler.add_systems(AppStage::Update, transform_system_bundle);
|
||||||
|
scheduler.add_system(AppStage::Update, build_rotator_system());
|
||||||
|
|
||||||
|
// plane
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
plane_handle.clone(),
|
||||||
|
Material::new(math::vec4(0.1, 0.2, 0.1, 1.0)),
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
Translation::new(0.0, 0.0, -5.0)
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// cube
|
||||||
|
let parent_cube = *world.insert((), vec![
|
||||||
|
(
|
||||||
|
cube_handle.clone(),
|
||||||
|
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0)),
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
Translation::new(0.0, 0.0, 1.0),
|
||||||
|
Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||||
|
Rotator,
|
||||||
|
)
|
||||||
|
]).first().unwrap();
|
||||||
|
|
||||||
|
// cube
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
cube_handle,
|
||||||
|
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0)),
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
Translation::new(0.0, 0.0, 3.0),
|
||||||
|
Parent(parent_cube),
|
||||||
|
LocalToParent::identity(),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// light
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
Light {
|
||||||
|
color: wgpu::Color {
|
||||||
|
r: 0.8,
|
||||||
|
g: 0.8,
|
||||||
|
b: 0.5,
|
||||||
|
a: 1.0,
|
||||||
|
},
|
||||||
|
fov: f32::to_radians(60.0),
|
||||||
|
depth: 0.1 .. 50.0,
|
||||||
|
target_view: None,
|
||||||
|
},
|
||||||
|
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0)),
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
Translation::new(4.0, -4.0, 5.0),
|
||||||
|
Rotation::from_euler_angles(0.0, 0.0, 0.0)
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// camera
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
Camera::new(CameraType::Projection {
|
||||||
|
fov: std::f32::consts::PI / 4.0,
|
||||||
|
near: 1.0,
|
||||||
|
far: 1000.0,
|
||||||
|
aspect_ratio: 1.0,
|
||||||
|
}),
|
||||||
|
ActiveCamera,
|
||||||
|
LocalToWorld(Mat4::look_at_rh(
|
||||||
|
Vec3::new(3.0, -15.0, 8.0),
|
||||||
|
Vec3::new(0.0, 0.0, 0.0),
|
||||||
|
Vec3::new(0.0, 0.0, 1.0),)),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
|
@ -1,200 +1,46 @@
|
||||||
use bevy::*;
|
use bevy::{*, render::*, asset::{Asset, AssetStorage}, math::{Mat4, Vec3}};
|
||||||
use bevy::{render::*, asset::{Asset, AssetStorage, Handle}, math::{Mat4, Quat, Vec3}, Schedulable, Parent};
|
|
||||||
use rand::{rngs::StdRng, Rng, SeedableRng, random};
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
|
|
||||||
fn build_wander_system() -> Box<dyn Schedulable> {
|
|
||||||
let mut rng = StdRng::from_entropy();
|
|
||||||
|
|
||||||
SystemBuilder::new("Wander")
|
|
||||||
.read_resource::<Time>()
|
|
||||||
.with_query(<(
|
|
||||||
Read<Person>,
|
|
||||||
Read<Translation>,
|
|
||||||
Write<Wander>,
|
|
||||||
Write<NavigationPoint>,
|
|
||||||
)>::query())
|
|
||||||
.build(move |
|
|
||||||
_, world,
|
|
||||||
time ,
|
|
||||||
person_query| {
|
|
||||||
for (_, translation, mut wander, mut navigation_point) in person_query.iter(world) {
|
|
||||||
wander.elapsed += time.delta_seconds;
|
|
||||||
if wander.elapsed >= wander.duration {
|
|
||||||
let direction = math::vec3(
|
|
||||||
rng.gen_range(-1.0, 1.0),
|
|
||||||
rng.gen_range(-1.0, 1.0),
|
|
||||||
rng.gen_range(0.0, 0.001),
|
|
||||||
).normalize();
|
|
||||||
let distance = rng.gen_range(wander.distance_bounds.x(), wander.distance_bounds.y());
|
|
||||||
navigation_point.target = translation.0 + direction * distance;
|
|
||||||
wander.elapsed = 0.0;
|
|
||||||
wander.duration = rng.gen_range(wander.duration_bounds.x(), wander.duration_bounds.y());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_navigate_system() -> Box<dyn Schedulable> {
|
|
||||||
SystemBuilder::new("Navigate")
|
|
||||||
.with_query(<(
|
|
||||||
Read<Person>,
|
|
||||||
Write<Translation>,
|
|
||||||
Write<Velocity>,
|
|
||||||
Write<NavigationPoint>,
|
|
||||||
)>::query())
|
|
||||||
.build(move |
|
|
||||||
_, world,
|
|
||||||
_, person_query| {
|
|
||||||
for (_, translation, mut velocity, navigation_point) in person_query.iter(world) {
|
|
||||||
let distance = navigation_point.target - translation.0;
|
|
||||||
if distance.length() > 0.01 {
|
|
||||||
let direction = distance.normalize();
|
|
||||||
velocity.value = direction * 2.0;
|
|
||||||
} else {
|
|
||||||
velocity.value = math::vec3(0.0, 0.0, 0.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_move_system() -> Box<dyn Schedulable> {
|
|
||||||
SystemBuilder::new("Move")
|
|
||||||
.read_resource::<Time>()
|
|
||||||
.with_query(<(
|
|
||||||
Write<Translation>,
|
|
||||||
Read<Velocity>,
|
|
||||||
)>::query())
|
|
||||||
.build(move |_, world, time , person_query| {
|
|
||||||
for (mut translation, velocity) in person_query.iter(world) {
|
|
||||||
translation.0 += velocity.value * time.delta_seconds;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_print_status_system() -> Box<dyn Schedulable> {
|
|
||||||
let mut elapsed = 0.0;
|
|
||||||
let mut frame_time_total = 0.0;
|
|
||||||
let mut frame_time_count = 0;
|
|
||||||
let frame_time_max = 10;
|
|
||||||
let mut frame_time_values = VecDeque::new();
|
|
||||||
SystemBuilder::new("PrintStatus")
|
|
||||||
.read_resource::<Time>()
|
|
||||||
.with_query(<(
|
|
||||||
Read<Person>,
|
|
||||||
)>::query())
|
|
||||||
.build(move |_, world, time , person_query| {
|
|
||||||
elapsed += time.delta_seconds;
|
|
||||||
frame_time_values.push_front(time.delta_seconds);
|
|
||||||
frame_time_total += time.delta_seconds;
|
|
||||||
frame_time_count += 1;
|
|
||||||
if frame_time_count > frame_time_max {
|
|
||||||
frame_time_count = frame_time_max;
|
|
||||||
frame_time_total -= frame_time_values.pop_back().unwrap();
|
|
||||||
}
|
|
||||||
if elapsed > 1.0 {
|
|
||||||
// println!("fps: {}", if time.delta_seconds == 0.0 { 0.0 } else { 1.0 / time.delta_seconds });
|
|
||||||
if frame_time_count > 0 && frame_time_total > 0.0 {
|
|
||||||
println!("fps: {}", 1.0 / (frame_time_total / frame_time_count as f32))
|
|
||||||
}
|
|
||||||
println!("peeps: {}", person_query.iter(world).count());
|
|
||||||
elapsed = 0.0;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_spawner_system(world: &mut World) -> Box<dyn Schedulable> {
|
|
||||||
let mesh_handle = {
|
|
||||||
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh, MeshType>>().unwrap();
|
|
||||||
mesh_storage.get_named("cube").unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let duration = 0.5;
|
|
||||||
let mut elapsed = duration;
|
|
||||||
let batch_size = 100;
|
|
||||||
|
|
||||||
SystemBuilder::new("Spawner")
|
|
||||||
.read_resource::<Time>()
|
|
||||||
.with_query(<(
|
|
||||||
Read<Person>,
|
|
||||||
)>::query())
|
|
||||||
.build(move |command_buffer, _, time , _| {
|
|
||||||
elapsed += time.delta_seconds;
|
|
||||||
if elapsed > duration {
|
|
||||||
for _ in 0..batch_size {
|
|
||||||
spawn_person(command_buffer, mesh_handle.clone());
|
|
||||||
}
|
|
||||||
elapsed = 0.0;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_light_rotator_system() -> Box<dyn Schedulable> {
|
|
||||||
SystemBuilder::new("LightRotator")
|
|
||||||
.read_resource::<Time>()
|
|
||||||
.with_query(<(
|
|
||||||
Write<Light>,
|
|
||||||
Write<Rotation>,
|
|
||||||
)>::query())
|
|
||||||
.build(move |_, world, time , light_query| {
|
|
||||||
for (_, mut rotation) in light_query.iter(world) {
|
|
||||||
rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Person {
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Velocity {
|
|
||||||
pub value: math::Vec3,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NavigationPoint {
|
|
||||||
pub target: math::Vec3,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Wander {
|
|
||||||
pub duration_bounds: math::Vec2,
|
|
||||||
pub distance_bounds: math::Vec2,
|
|
||||||
pub duration: f32,
|
|
||||||
pub elapsed: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let universe = Universe::new();
|
AppBuilder::new()
|
||||||
let mut world = universe.create_world();
|
.add_defaults()
|
||||||
let mut scheduler = SystemScheduler::<ApplicationStage>::new();
|
.setup(&setup)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
|
||||||
let cube = Mesh::load(MeshType::Cube);
|
let cube = Mesh::load(MeshType::Cube);
|
||||||
let plane = Mesh::load(MeshType::Plane{ size: 24.5 });
|
let plane = Mesh::load(MeshType::Plane{ size: 10.0 });
|
||||||
let mut mesh_storage = AssetStorage::<Mesh, MeshType>::new();
|
|
||||||
|
|
||||||
let _cube_handle = mesh_storage.add(cube, "cube");
|
let (cube_handle, plane_handle) = {
|
||||||
let plane_handle = mesh_storage.add(plane, "plane");
|
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh, MeshType>>().unwrap();
|
||||||
world.resources.insert(mesh_storage);
|
(mesh_storage.add(cube, "cube"), mesh_storage.add(plane, "plane"))
|
||||||
|
};
|
||||||
|
|
||||||
let transform_system_bundle = transform_system_bundle::build(&mut world);
|
let transform_system_bundle = transform_system_bundle::build(world);
|
||||||
scheduler.add_systems(ApplicationStage::Update, transform_system_bundle);
|
scheduler.add_systems(AppStage::Update, transform_system_bundle);
|
||||||
scheduler.add_system(ApplicationStage::Update, build_wander_system());
|
|
||||||
scheduler.add_system(ApplicationStage::Update, build_navigate_system());
|
|
||||||
scheduler.add_system(ApplicationStage::Update, build_move_system());
|
|
||||||
// scheduler.add_system(ApplicationStage::Update, build_light_rotator_system());
|
|
||||||
// scheduler.add_system(ApplicationStage::Update, build_spawner_system(&mut world));
|
|
||||||
scheduler.add_system(ApplicationStage::Update, build_print_status_system());
|
|
||||||
|
|
||||||
// world.insert((), vec![
|
// plane
|
||||||
// // plane
|
world.insert((), vec![
|
||||||
// (
|
(
|
||||||
// Material::new(math::vec4(0.1, 0.2, 0.1, 1.0)),
|
plane_handle.clone(),
|
||||||
// plane_handle.clone(),
|
Material::new(math::vec4(0.1, 0.2, 0.1, 1.0)),
|
||||||
// LocalToWorld::identity(),
|
LocalToWorld::identity(),
|
||||||
// Translation::new(0.0, 0.0, 0.0)
|
Translation::new(0.0, 0.0, 0.0)
|
||||||
// ),
|
),
|
||||||
// ]);
|
]);
|
||||||
|
|
||||||
let x = *world.insert((), vec![
|
// cube
|
||||||
// lights
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
cube_handle,
|
||||||
|
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0)),
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
Translation::new(0.0, 0.0, 1.0)
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// light
|
||||||
|
world.insert((), vec![
|
||||||
(
|
(
|
||||||
Light {
|
Light {
|
||||||
color: wgpu::Color {
|
color: wgpu::Color {
|
||||||
|
@ -208,45 +54,14 @@ fn main() {
|
||||||
target_view: None,
|
target_view: None,
|
||||||
},
|
},
|
||||||
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0)),
|
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0)),
|
||||||
// _cube_handle.clone(),
|
|
||||||
LocalToWorld::identity(),
|
LocalToWorld::identity(),
|
||||||
Translation::new(4.0, -4.0, 5.0),
|
Translation::new(4.0, -4.0, 5.0),
|
||||||
Rotation::from_euler_angles(0.0, 0.0, 0.0)
|
Rotation::from_euler_angles(0.0, 0.0, 0.0)
|
||||||
),
|
),
|
||||||
// (
|
]);
|
||||||
// Light {
|
|
||||||
// color: wgpu::Color {
|
|
||||||
// r: 1.0,
|
|
||||||
// g: 0.5,
|
|
||||||
// b: 0.5,
|
|
||||||
// a: 1.0,
|
|
||||||
// },
|
|
||||||
// fov: f32::to_radians(45.0),
|
|
||||||
// depth: 1.0 .. 20.0,
|
|
||||||
// target_view: None,
|
|
||||||
// },
|
|
||||||
// // Material::new(math::vec4(0.5, 0.3, 0.3, 1.0) * random::<f32>()),
|
|
||||||
// // cube_handle.clone(),
|
|
||||||
// LocalToWorld::identity(),
|
|
||||||
// Translation::new(-5.0, 7.0, 10.0)
|
|
||||||
// ),
|
|
||||||
]).first().unwrap();
|
|
||||||
|
|
||||||
// world.insert((), vec![
|
|
||||||
// (
|
|
||||||
// Material::new(math::vec4(1.0, 1.0, 1.0, 1.0)),
|
|
||||||
// _cube_handle.clone(),
|
|
||||||
// LocalToWorld::identity(),
|
|
||||||
// Translation::new(0.0, 0.0, 3.0),
|
|
||||||
// Scale(1.0),
|
|
||||||
// Parent(x),
|
|
||||||
// LocalToParent::identity(),
|
|
||||||
// )
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
world.insert((), vec![
|
|
||||||
|
|
||||||
// camera
|
// camera
|
||||||
|
world.insert((), vec![
|
||||||
(
|
(
|
||||||
Camera::new(CameraType::Projection {
|
Camera::new(CameraType::Projection {
|
||||||
fov: std::f32::consts::PI / 4.0,
|
fov: std::f32::consts::PI / 4.0,
|
||||||
|
@ -256,114 +71,9 @@ fn main() {
|
||||||
}),
|
}),
|
||||||
ActiveCamera,
|
ActiveCamera,
|
||||||
LocalToWorld(Mat4::look_at_rh(
|
LocalToWorld(Mat4::look_at_rh(
|
||||||
Vec3::new(6.0, -40.0, 20.0),
|
Vec3::new(3.0, -8.0, 5.0),
|
||||||
Vec3::new(0.0, 0.0, 0.0),
|
Vec3::new(0.0, 0.0, 0.0),
|
||||||
Vec3::new(0.0, 0.0, 1.0),)),
|
Vec3::new(0.0, 0.0, 1.0),)),
|
||||||
// Translation::new(0.0, 0.0, 0.0),
|
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
world.insert((), vec![
|
|
||||||
|
|
||||||
// camera
|
|
||||||
(
|
|
||||||
Camera::new(CameraType::Orthographic {
|
|
||||||
left: 0.0,
|
|
||||||
right: 0.0,
|
|
||||||
bottom: 0.0,
|
|
||||||
top: 0.0,
|
|
||||||
near: 0.0,
|
|
||||||
far: 1.0,
|
|
||||||
}),
|
|
||||||
ActiveCamera2d,
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
|
|
||||||
world.insert((), vec![
|
|
||||||
(
|
|
||||||
Rect {
|
|
||||||
position: math::vec2(75.0, 75.0),
|
|
||||||
dimensions: math::vec2(100.0, 100.0),
|
|
||||||
color: math::vec4(0.0, 1.0, 0.0, 1.0),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
|
|
||||||
world.insert((), vec![
|
|
||||||
(
|
|
||||||
Rect {
|
|
||||||
position: math::vec2(50.0, 50.0),
|
|
||||||
dimensions: math::vec2(100.0, 100.0),
|
|
||||||
color: math::vec4(1.0, 0.0, 0.0, 1.0),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
|
|
||||||
world.insert((), vec![
|
|
||||||
(
|
|
||||||
Rect {
|
|
||||||
position: math::vec2(100.0, 100.0),
|
|
||||||
dimensions: math::vec2(100.0, 100.0),
|
|
||||||
color: math::vec4(0.0, 0.0, 1.0, 1.0),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
|
|
||||||
let mut rng = StdRng::from_entropy();
|
|
||||||
for _ in 0 .. 5 {
|
|
||||||
create_person(&mut world, _cube_handle.clone(),
|
|
||||||
Translation::new(rng.gen_range(-50.0, 50.0), 0.0, rng.gen_range(-50.0, 50.0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Application::run(universe, world, scheduler);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spawn_person(command_buffer: &mut CommandBuffer, mesh_handle: Handle<Mesh>) {
|
|
||||||
command_buffer.insert((), vec![
|
|
||||||
(
|
|
||||||
Person{},
|
|
||||||
Wander {
|
|
||||||
duration_bounds: math::vec2(3.0, 10.0),
|
|
||||||
distance_bounds: math::vec2(-50.0, 50.0),
|
|
||||||
elapsed: 0.0,
|
|
||||||
duration: 0.0,
|
|
||||||
},
|
|
||||||
NavigationPoint {
|
|
||||||
target: math::vec3(0.0, 0.0, 0.0),
|
|
||||||
},
|
|
||||||
Velocity {
|
|
||||||
value: math::vec3(0.0, 0.0, 0.0),
|
|
||||||
},
|
|
||||||
Instanced,
|
|
||||||
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0) * random::<f32>()),
|
|
||||||
mesh_handle.clone(),
|
|
||||||
LocalToWorld::identity(),
|
|
||||||
Translation::new(0.0, 0.0, 1.0)
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_person(world: &mut World, mesh_handle: Handle<Mesh>, translation: Translation) {
|
|
||||||
world.insert((), vec![
|
|
||||||
(
|
|
||||||
Person{},
|
|
||||||
Wander {
|
|
||||||
duration_bounds: math::vec2(3.0, 10.0),
|
|
||||||
distance_bounds: math::vec2(-50.0, 50.0),
|
|
||||||
elapsed: 0.0,
|
|
||||||
duration: 0.0,
|
|
||||||
},
|
|
||||||
NavigationPoint {
|
|
||||||
target: math::vec3(0.0, 0.0, 0.0),
|
|
||||||
},
|
|
||||||
Velocity {
|
|
||||||
value: math::vec3(0.0, 0.0, 0.0),
|
|
||||||
},
|
|
||||||
Instanced,
|
|
||||||
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0) * random::<f32>()),
|
|
||||||
mesh_handle,
|
|
||||||
LocalToWorld::identity(),
|
|
||||||
translation
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
}
|
108
examples/ui.rs
Normal file
108
examples/ui.rs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
use bevy::{*, render::*, asset::{Asset, AssetStorage}, math::{Mat4, Vec3}};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
AppBuilder::new()
|
||||||
|
.add_defaults()
|
||||||
|
.setup(&setup)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
|
||||||
|
let cube = Mesh::load(MeshType::Cube);
|
||||||
|
let cube_handle = {
|
||||||
|
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh, MeshType>>().unwrap();
|
||||||
|
mesh_storage.add(cube, "cube")
|
||||||
|
};
|
||||||
|
|
||||||
|
let transform_system_bundle = transform_system_bundle::build(world);
|
||||||
|
scheduler.add_systems(AppStage::Update, transform_system_bundle);
|
||||||
|
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
cube_handle,
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0)),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
Light {
|
||||||
|
color: wgpu::Color {
|
||||||
|
r: 0.8,
|
||||||
|
g: 0.8,
|
||||||
|
b: 0.5,
|
||||||
|
a: 1.0,
|
||||||
|
},
|
||||||
|
fov: f32::to_radians(60.0),
|
||||||
|
depth: 0.1 .. 50.0,
|
||||||
|
target_view: None,
|
||||||
|
},
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
Translation::new(4.0, -4.0, 5.0),
|
||||||
|
Rotation::from_euler_angles(0.0, 0.0, 0.0)
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
world.insert((), vec![
|
||||||
|
// camera
|
||||||
|
(
|
||||||
|
Camera::new(CameraType::Projection {
|
||||||
|
fov: std::f32::consts::PI / 4.0,
|
||||||
|
near: 1.0,
|
||||||
|
far: 1000.0,
|
||||||
|
aspect_ratio: 1.0,
|
||||||
|
}),
|
||||||
|
ActiveCamera,
|
||||||
|
LocalToWorld(Mat4::look_at_rh(
|
||||||
|
Vec3::new(3.0, -5.0, 3.0),
|
||||||
|
Vec3::new(0.0, 0.0, 0.0),
|
||||||
|
Vec3::new(0.0, 0.0, 1.0),)),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
world.insert((), vec![
|
||||||
|
// camera
|
||||||
|
(
|
||||||
|
Camera::new(CameraType::Orthographic {
|
||||||
|
left: 0.0,
|
||||||
|
right: 0.0,
|
||||||
|
bottom: 0.0,
|
||||||
|
top: 0.0,
|
||||||
|
near: 0.0,
|
||||||
|
far: 1.0,
|
||||||
|
}),
|
||||||
|
ActiveCamera2d,
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
Rect {
|
||||||
|
position: math::vec2(75.0, 75.0),
|
||||||
|
dimensions: math::vec2(100.0, 100.0),
|
||||||
|
color: math::vec4(0.0, 1.0, 0.0, 1.0),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
Rect {
|
||||||
|
position: math::vec2(50.0, 50.0),
|
||||||
|
dimensions: math::vec2(100.0, 100.0),
|
||||||
|
color: math::vec4(1.0, 0.0, 0.0, 1.0),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
world.insert((), vec![
|
||||||
|
(
|
||||||
|
Rect {
|
||||||
|
position: math::vec2(100.0, 100.0),
|
||||||
|
dimensions: math::vec2(100.0, 100.0),
|
||||||
|
color: math::vec4(0.0, 0.0, 1.0, 1.0),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
55
src/app/app_builder.rs
Normal file
55
src/app/app_builder.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use crate::{App, asset::AssetStorage, legion::prelude::{World, SystemScheduler}, render::{*, passes::*}, AppStage, Time};
|
||||||
|
|
||||||
|
pub struct AppBuilder {
|
||||||
|
pub app: App,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppBuilder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let world = World::new();
|
||||||
|
let scheduler = SystemScheduler::<AppStage>::new();
|
||||||
|
AppBuilder {
|
||||||
|
app: App::new(world, scheduler),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> App {
|
||||||
|
self.app
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(self) {
|
||||||
|
self.app.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup(mut self, setup: &dyn Fn(&mut World, &mut SystemScheduler<AppStage>)) -> Self {
|
||||||
|
setup(&mut self.app.world, &mut self.app.scheduler);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_default_passes(mut self) -> Self {
|
||||||
|
self.app.render_graph.add_render_resource_manager(Box::new(render_resources::MaterialResourceManager));
|
||||||
|
self.app.render_graph.add_render_resource_manager(Box::new(render_resources::LightResourceManager::new(10)));
|
||||||
|
self.app.render_graph.add_render_resource_manager(Box::new(render_resources::GlobalResourceManager));
|
||||||
|
self.app.render_graph.add_render_resource_manager(Box::new(render_resources::Global2dResourceManager));
|
||||||
|
|
||||||
|
let depth_format = wgpu::TextureFormat::Depth32Float;
|
||||||
|
self.app.render_graph.set_pass("forward", Box::new(ForwardPass::new(depth_format)));
|
||||||
|
self.app.render_graph.set_pipeline("forward", "forward", Box::new(ForwardPipeline::new()));
|
||||||
|
self.app.render_graph.set_pipeline("forward", "forward_instanced", Box::new(ForwardInstancedPipeline::new(depth_format)));
|
||||||
|
self.app.render_graph.set_pipeline("forward", "ui", Box::new(UiPipeline::new()));
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_default_resources(mut self) -> Self {
|
||||||
|
self.app.world.resources.insert(Time::new());
|
||||||
|
self.app.world.resources.insert(AssetStorage::<Mesh, MeshType>::new());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_defaults(self) -> Self {
|
||||||
|
self
|
||||||
|
.add_default_resources()
|
||||||
|
.add_default_passes()
|
||||||
|
}
|
||||||
|
}
|
18
src/app/app_stage.rs
Normal file
18
src/app/app_stage.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
use legion::schedule::Stage;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum AppStage {
|
||||||
|
Update,
|
||||||
|
Render,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stage for AppStage {}
|
||||||
|
|
||||||
|
impl std::fmt::Display for AppStage {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
AppStage::Update => write!(f, "update"),
|
||||||
|
AppStage::Render => write!(f, "draw"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,9 @@
|
||||||
|
mod app_stage;
|
||||||
|
mod app_builder;
|
||||||
|
|
||||||
|
pub use app_stage::AppStage;
|
||||||
|
pub use app_builder::AppBuilder;
|
||||||
|
|
||||||
use winit::{
|
use winit::{
|
||||||
event,
|
event,
|
||||||
event::WindowEvent,
|
event::WindowEvent,
|
||||||
|
@ -7,29 +13,26 @@ use winit::{
|
||||||
|
|
||||||
use legion::prelude::*;
|
use legion::prelude::*;
|
||||||
|
|
||||||
use crate::{render::*, render::passes::*, ApplicationStage, Time};
|
use crate::{render::*, Time};
|
||||||
|
|
||||||
pub struct Application
|
pub struct App
|
||||||
{
|
{
|
||||||
pub universe: Universe,
|
|
||||||
pub world: World,
|
pub world: World,
|
||||||
pub window: Window,
|
pub window: Option<Window>,
|
||||||
pub render_graph: RenderGraph,
|
pub render_graph: RenderGraph,
|
||||||
pub scheduler: SystemScheduler<ApplicationStage>,
|
pub swap_chain: Option<wgpu::SwapChain>,
|
||||||
|
pub scheduler: SystemScheduler<AppStage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application {
|
impl App {
|
||||||
fn add_default_passes(&mut self) {
|
pub fn new(world: World, scheduler: SystemScheduler<AppStage>) -> App {
|
||||||
self.render_graph.add_render_resource_manager(Box::new(render_resources::MaterialResourceManager));
|
App {
|
||||||
self.render_graph.add_render_resource_manager(Box::new(render_resources::LightResourceManager::new(10)));
|
world: world,
|
||||||
self.render_graph.add_render_resource_manager(Box::new(render_resources::GlobalResourceManager));
|
scheduler: scheduler,
|
||||||
self.render_graph.add_render_resource_manager(Box::new(render_resources::Global2dResourceManager));
|
render_graph: RenderGraph::new(),
|
||||||
|
swap_chain: None,
|
||||||
let depth_format = wgpu::TextureFormat::Depth32Float;
|
window: None,
|
||||||
self.render_graph.set_pass("forward", Box::new(ForwardPass::new(depth_format)));
|
}
|
||||||
self.render_graph.set_pipeline("forward", "forward", Box::new(ForwardPipeline::new()));
|
|
||||||
self.render_graph.set_pipeline("forward", "forward_instanced", Box::new(ForwardInstancedPipeline::new(depth_format)));
|
|
||||||
self.render_graph.set_pipeline("forward", "ui", Box::new(UiPipeline::new()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self) {
|
fn update(&mut self) {
|
||||||
|
@ -47,7 +50,7 @@ impl Application {
|
||||||
|
|
||||||
fn resize(&mut self, width: u32, height: u32)
|
fn resize(&mut self, width: u32, height: u32)
|
||||||
{
|
{
|
||||||
self.render_graph.resize(width, height, &mut self.world);
|
self.swap_chain = Some(self.render_graph.resize(width, height, &mut self.world));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&mut self, _: WindowEvent)
|
fn handle_event(&mut self, _: WindowEvent)
|
||||||
|
@ -56,11 +59,10 @@ impl Application {
|
||||||
|
|
||||||
fn render(&mut self)
|
fn render(&mut self)
|
||||||
{
|
{
|
||||||
self.render_graph.render(&mut self.world);
|
self.render_graph.render(&mut self.world, self.swap_chain.as_mut().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
pub fn run(mut self) {
|
||||||
pub fn run(universe: Universe, mut world: World, system_scheduler: SystemScheduler<ApplicationStage>) {
|
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
log::info!("Initializing the window...");
|
log::info!("Initializing the window...");
|
||||||
|
@ -80,14 +82,14 @@ impl Application {
|
||||||
limits: wgpu::Limits::default(),
|
limits: wgpu::Limits::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let (window, hidpi_factor, size, surface) = {
|
let (window, size, surface) = {
|
||||||
let window = winit::window::Window::new(&event_loop).unwrap();
|
let window = winit::window::Window::new(&event_loop).unwrap();
|
||||||
window.set_title("bevy");
|
window.set_title("bevy");
|
||||||
window.set_inner_size((1280, 720).into());
|
window.set_inner_size((1280, 720).into());
|
||||||
let hidpi_factor = window.hidpi_factor();
|
let hidpi_factor = window.hidpi_factor();
|
||||||
let size = window.inner_size().to_physical(hidpi_factor);
|
let size = window.inner_size().to_physical(hidpi_factor);
|
||||||
let surface = wgpu::Surface::create(&window);
|
let surface = wgpu::Surface::create(&window);
|
||||||
(window, hidpi_factor, size, surface)
|
(window, size, surface)
|
||||||
};
|
};
|
||||||
|
|
||||||
let swap_chain_descriptor = wgpu::SwapChainDescriptor {
|
let swap_chain_descriptor = wgpu::SwapChainDescriptor {
|
||||||
|
@ -99,20 +101,11 @@ impl Application {
|
||||||
};
|
};
|
||||||
let swap_chain = device.create_swap_chain(&surface, &swap_chain_descriptor);
|
let swap_chain = device.create_swap_chain(&surface, &swap_chain_descriptor);
|
||||||
|
|
||||||
world.resources.insert(Time::new());
|
|
||||||
|
|
||||||
log::info!("Initializing the example...");
|
log::info!("Initializing the example...");
|
||||||
let render_graph = RenderGraph::new(device, swap_chain_descriptor, swap_chain, queue, surface);
|
self.render_graph.initialize(&mut self.world, device, swap_chain_descriptor, queue, surface);
|
||||||
let mut app = Application {
|
self.window = Some(window);
|
||||||
universe,
|
self.swap_chain = Some(swap_chain);
|
||||||
world,
|
|
||||||
window,
|
|
||||||
render_graph,
|
|
||||||
scheduler: system_scheduler,
|
|
||||||
};
|
|
||||||
|
|
||||||
app.add_default_passes();
|
|
||||||
app.render_graph.initialize(&mut app.world);
|
|
||||||
|
|
||||||
log::info!("Entering render loop...");
|
log::info!("Entering render loop...");
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| {
|
||||||
|
@ -126,11 +119,12 @@ impl Application {
|
||||||
event: WindowEvent::Resized(size),
|
event: WindowEvent::Resized(size),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let hidpi_factor = self.window.as_ref().unwrap().hidpi_factor();
|
||||||
let physical = size.to_physical(hidpi_factor);
|
let physical = size.to_physical(hidpi_factor);
|
||||||
log::info!("Resizing to {:?}", physical);
|
log::info!("Resizing to {:?}", physical);
|
||||||
let width = physical.width.round() as u32;
|
let width = physical.width.round() as u32;
|
||||||
let height = physical.height.round() as u32;
|
let height = physical.height.round() as u32;
|
||||||
app.resize(width, height);
|
self.resize(width, height);
|
||||||
}
|
}
|
||||||
event::Event::WindowEvent { event, .. } => match event {
|
event::Event::WindowEvent { event, .. } => match event {
|
||||||
WindowEvent::KeyboardInput {
|
WindowEvent::KeyboardInput {
|
||||||
|
@ -146,11 +140,11 @@ impl Application {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
app.handle_event(event);
|
self.handle_event(event);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
event::Event::EventsCleared => {
|
event::Event::EventsCleared => {
|
||||||
app.update();
|
self.update();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
|
@ -1,21 +1,2 @@
|
||||||
use legion::schedule::Stage;
|
|
||||||
|
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub use time::Time;
|
pub use time::Time;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub enum ApplicationStage {
|
|
||||||
Update,
|
|
||||||
Render,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Stage for ApplicationStage {}
|
|
||||||
|
|
||||||
impl std::fmt::Display for ApplicationStage {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
ApplicationStage::Update => write!(f, "update"),
|
|
||||||
ApplicationStage::Render => write!(f, "draw"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
pub mod render;
|
pub mod render;
|
||||||
pub mod asset;
|
pub mod asset;
|
||||||
mod application;
|
mod app;
|
||||||
mod vertex;
|
mod vertex;
|
||||||
mod core;
|
mod core;
|
||||||
|
|
||||||
pub use application::Application;
|
pub use app::{App, AppStage, AppBuilder};
|
||||||
pub use crate::core::*;
|
pub use crate::core::*;
|
||||||
|
|
||||||
pub use wgpu;
|
pub use wgpu;
|
||||||
|
|
|
@ -24,6 +24,10 @@ impl ForwardInstancedPipeline {
|
||||||
fn create_instance_buffer_infos(device: &Device, world: &World) -> Vec<InstanceBufferInfo> {
|
fn create_instance_buffer_infos(device: &Device, world: &World) -> Vec<InstanceBufferInfo> {
|
||||||
let mut entities = <(Read<Material>, Read<LocalToWorld>, Read<Handle<Mesh>>, Read<Instanced>)>::query();
|
let mut entities = <(Read<Material>, Read<LocalToWorld>, Read<Handle<Mesh>>, Read<Instanced>)>::query();
|
||||||
let entities_count = entities.iter_immutable(world).count();
|
let entities_count = entities.iter_immutable(world).count();
|
||||||
|
if entities_count == 0 {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
let size = mem::size_of::<SimpleMaterialUniforms>();
|
let size = mem::size_of::<SimpleMaterialUniforms>();
|
||||||
|
|
||||||
// TODO: use a staging buffer for more efficient gpu reads
|
// TODO: use a staging buffer for more efficient gpu reads
|
||||||
|
|
|
@ -33,6 +33,10 @@ impl UiPipeline {
|
||||||
let mut rect_query = <Read<Rect>>::query();
|
let mut rect_query = <Read<Rect>>::query();
|
||||||
let rect_count = rect_query.iter_immutable(world).count();
|
let rect_count = rect_query.iter_immutable(world).count();
|
||||||
|
|
||||||
|
if rect_count == 0 {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
let mut data = Vec::with_capacity(rect_count);
|
let mut data = Vec::with_capacity(rect_count);
|
||||||
// TODO: this probably isn't the best way to handle z-ordering
|
// TODO: this probably isn't the best way to handle z-ordering
|
||||||
let mut z = 0.9999;
|
let mut z = 0.9999;
|
||||||
|
|
|
@ -11,12 +11,11 @@ use std::collections::HashMap;
|
||||||
use legion::world::World;
|
use legion::world::World;
|
||||||
|
|
||||||
pub struct RenderGraph {
|
pub struct RenderGraph {
|
||||||
pub data: RenderGraphData,
|
pub data: Option<RenderGraphData>,
|
||||||
passes: HashMap<String, Box<dyn Pass>>,
|
passes: HashMap<String, Box<dyn Pass>>,
|
||||||
pipelines: HashMap<String, Box<dyn Pipeline>>,
|
pipelines: HashMap<String, Box<dyn Pipeline>>,
|
||||||
pass_pipelines: HashMap<String, Vec<String>>,
|
pass_pipelines: HashMap<String, Vec<String>>,
|
||||||
render_resource_managers: Vec<Box<dyn RenderResourceManager>>,
|
render_resource_managers: Vec<Box<dyn RenderResourceManager>>,
|
||||||
pub swap_chain: wgpu::SwapChain, // TODO: this is weird
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RenderGraphData {
|
pub struct RenderGraphData {
|
||||||
|
@ -77,53 +76,56 @@ impl RenderGraphData {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderGraph {
|
impl RenderGraph {
|
||||||
pub fn new(device: wgpu::Device, swap_chain_descriptor: wgpu::SwapChainDescriptor, swap_chain: wgpu::SwapChain, queue: wgpu::Queue, surface: wgpu::Surface) -> Self {
|
pub fn new() -> Self {
|
||||||
RenderGraph {
|
RenderGraph {
|
||||||
passes: HashMap::new(),
|
passes: HashMap::new(),
|
||||||
pipelines: HashMap::new(),
|
pipelines: HashMap::new(),
|
||||||
swap_chain,
|
|
||||||
pass_pipelines: HashMap::new(),
|
pass_pipelines: HashMap::new(),
|
||||||
render_resource_managers: Vec::new(),
|
render_resource_managers: Vec::new(),
|
||||||
data: RenderGraphData::new(device, swap_chain_descriptor, queue, surface),
|
data: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize(&mut self, world: &mut World) {
|
pub fn initialize(&mut self, world: &mut World, device: wgpu::Device, swap_chain_descriptor: wgpu::SwapChainDescriptor, queue: wgpu::Queue, surface: wgpu::Surface) {
|
||||||
|
let mut data = RenderGraphData::new(device, swap_chain_descriptor, queue, surface);
|
||||||
for render_resource_manager in self.render_resource_managers.iter_mut() {
|
for render_resource_manager in self.render_resource_managers.iter_mut() {
|
||||||
render_resource_manager.initialize(&mut self.data, world);
|
render_resource_manager.initialize(&mut data, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
for pass in self.passes.values_mut() {
|
for pass in self.passes.values_mut() {
|
||||||
pass.initialize(&mut self.data);
|
pass.initialize(&mut data);
|
||||||
}
|
}
|
||||||
|
|
||||||
for pipeline in self.pipelines.values_mut() {
|
for pipeline in self.pipelines.values_mut() {
|
||||||
pipeline.initialize(&mut self.data, world);
|
pipeline.initialize(&mut data, world);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self, world: &mut World) {
|
self.data = Some(data);
|
||||||
let frame = self.swap_chain
|
}
|
||||||
|
|
||||||
|
pub fn render(&mut self, world: &mut World, swap_chain: &mut wgpu::SwapChain) {
|
||||||
|
let frame = swap_chain
|
||||||
.get_next_texture()
|
.get_next_texture()
|
||||||
.expect("Timeout when acquiring next swap chain texture");
|
.expect("Timeout when acquiring next swap chain texture");
|
||||||
|
|
||||||
|
let data = self.data.as_mut().unwrap();
|
||||||
let mut encoder =
|
let mut encoder =
|
||||||
self.data.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
data.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||||
|
|
||||||
for render_resource_manager in self.render_resource_managers.iter_mut() {
|
for render_resource_manager in self.render_resource_managers.iter_mut() {
|
||||||
render_resource_manager.update(&mut self.data, &mut encoder, world);
|
render_resource_manager.update(data, &mut encoder, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pass_name, pass) in self.passes.iter_mut() {
|
for (pass_name, pass) in self.passes.iter_mut() {
|
||||||
loop {
|
loop {
|
||||||
let render_pass = pass.begin(&mut self.data, world, &mut encoder, &frame);
|
let render_pass = pass.begin(data, world, &mut encoder, &frame);
|
||||||
if let Some(mut render_pass) = render_pass {
|
if let Some(mut render_pass) = render_pass {
|
||||||
// TODO: assign pipelines to specific passes
|
// TODO: assign pipelines to specific passes
|
||||||
if let Some(pipeline_names) = self.pass_pipelines.get(pass_name) {
|
if let Some(pipeline_names) = self.pass_pipelines.get(pass_name) {
|
||||||
for pipeline_name in pipeline_names.iter() {
|
for pipeline_name in pipeline_names.iter() {
|
||||||
let pipeline = self.pipelines.get_mut(pipeline_name).unwrap();
|
let pipeline = self.pipelines.get_mut(pipeline_name).unwrap();
|
||||||
render_pass.set_pipeline(pipeline.get_pipeline());
|
render_pass.set_pipeline(pipeline.get_pipeline());
|
||||||
pipeline.render(&mut self.data, &mut render_pass, &frame, world);
|
pipeline.render(data, &mut render_pass, &frame, world);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,32 +137,33 @@ impl RenderGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
let command_buffer = encoder.finish();
|
let command_buffer = encoder.finish();
|
||||||
self.data.queue.submit(&[command_buffer]);
|
data.queue.submit(&[command_buffer]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, width: u32, height: u32, world: &mut World) {
|
pub fn resize(&mut self, width: u32, height: u32, world: &mut World) -> wgpu::SwapChain {
|
||||||
self.data.swap_chain_descriptor.width = width;
|
let data = self.data.as_mut().unwrap();
|
||||||
self.data.swap_chain_descriptor.height = height;
|
data.swap_chain_descriptor.width = width;
|
||||||
self.swap_chain = self.data.device.create_swap_chain(&self.data.surface, &self.data.swap_chain_descriptor);
|
data.swap_chain_descriptor.height = height;
|
||||||
|
let swap_chain = data.device.create_swap_chain(&data.surface, &data.swap_chain_descriptor);
|
||||||
let mut encoder =
|
let mut encoder =
|
||||||
self.data.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
data.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||||
|
|
||||||
for render_resource_manager in self.render_resource_managers.iter_mut() {
|
for render_resource_manager in self.render_resource_managers.iter_mut() {
|
||||||
render_resource_manager.resize(&mut self.data, &mut encoder, world);
|
render_resource_manager.resize(data, &mut encoder, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
let command_buffer = encoder.finish();
|
let command_buffer = encoder.finish();
|
||||||
|
|
||||||
for pass in self.passes.values_mut() {
|
for pass in self.passes.values_mut() {
|
||||||
pass.resize(&mut self.data);
|
pass.resize(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
for pipeline in self.pipelines.values_mut() {
|
for pipeline in self.pipelines.values_mut() {
|
||||||
pipeline.resize(&mut self.data);
|
pipeline.resize(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.data.queue.submit(&[command_buffer]);
|
data.queue.submit(&[command_buffer]);
|
||||||
|
swap_chain
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_render_resource_manager(&mut self, render_resource_manager: Box<dyn RenderResourceManager>) {
|
pub fn add_render_resource_manager(&mut self, render_resource_manager: Box<dyn RenderResourceManager>) {
|
||||||
|
|
|
@ -42,6 +42,10 @@ impl RenderResourceManager for LightResourceManager {
|
||||||
let mut light_query = <(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
|
let mut light_query = <(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
|
||||||
let light_count = light_query.iter(world).count();
|
let light_count = light_query.iter(world).count();
|
||||||
|
|
||||||
|
if light_count == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.lights_are_dirty = false;
|
self.lights_are_dirty = false;
|
||||||
let size = mem::size_of::<LightRaw>();
|
let size = mem::size_of::<LightRaw>();
|
||||||
let total_size = size * light_count;
|
let total_size = size * light_count;
|
||||||
|
|
|
@ -26,6 +26,10 @@ impl RenderResourceManager for MaterialResourceManager {
|
||||||
let mut entities = <(Write<Material>, Read<LocalToWorld>)>::query()
|
let mut entities = <(Write<Material>, Read<LocalToWorld>)>::query()
|
||||||
.filter(!component::<Instanced>());
|
.filter(!component::<Instanced>());
|
||||||
let entities_count = entities.iter(world).count();
|
let entities_count = entities.iter(world).count();
|
||||||
|
if entities_count == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let size = mem::size_of::<MaterialUniforms>();
|
let size = mem::size_of::<MaterialUniforms>();
|
||||||
let temp_buf_data = render_graph.device
|
let temp_buf_data = render_graph.device
|
||||||
.create_buffer_mapped(entities_count * size, wgpu::BufferUsage::COPY_SRC);
|
.create_buffer_mapped(entities_count * size, wgpu::BufferUsage::COPY_SRC);
|
||||||
|
|
Loading…
Reference in a new issue