mirror of
https://github.com/bevyengine/bevy
synced 2024-11-24 05:33: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::*;
|
||||
|
||||
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();
|
||||
|
||||
// Application::run(universe, world, scheduler);
|
||||
AppBuilder::new()
|
||||
.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, 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,
|
||||
}
|
||||
use bevy::{*, render::*, asset::{Asset, AssetStorage}, math::{Mat4, Vec3}};
|
||||
|
||||
fn main() {
|
||||
let universe = Universe::new();
|
||||
let mut world = universe.create_world();
|
||||
let mut scheduler = SystemScheduler::<ApplicationStage>::new();
|
||||
AppBuilder::new()
|
||||
.add_defaults()
|
||||
.setup(&setup)
|
||||
.run();
|
||||
}
|
||||
|
||||
fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
|
||||
let cube = Mesh::load(MeshType::Cube);
|
||||
let plane = Mesh::load(MeshType::Plane{ size: 24.5 });
|
||||
let mut mesh_storage = AssetStorage::<Mesh, MeshType>::new();
|
||||
let plane = Mesh::load(MeshType::Plane{ size: 10.0 });
|
||||
|
||||
let _cube_handle = mesh_storage.add(cube, "cube");
|
||||
let plane_handle = mesh_storage.add(plane, "plane");
|
||||
world.resources.insert(mesh_storage);
|
||||
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(&mut world);
|
||||
scheduler.add_systems(ApplicationStage::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());
|
||||
let transform_system_bundle = transform_system_bundle::build(world);
|
||||
scheduler.add_systems(AppStage::Update, transform_system_bundle);
|
||||
|
||||
// world.insert((), vec![
|
||||
// // plane
|
||||
// (
|
||||
// Material::new(math::vec4(0.1, 0.2, 0.1, 1.0)),
|
||||
// plane_handle.clone(),
|
||||
// LocalToWorld::identity(),
|
||||
// Translation::new(0.0, 0.0, 0.0)
|
||||
// ),
|
||||
// ]);
|
||||
// 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, 0.0)
|
||||
),
|
||||
]);
|
||||
|
||||
// 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, 1.0)
|
||||
)
|
||||
]);
|
||||
|
||||
let x = *world.insert((), vec![
|
||||
// lights
|
||||
// light
|
||||
world.insert((), vec![
|
||||
(
|
||||
Light {
|
||||
color: wgpu::Color {
|
||||
|
@ -208,45 +54,14 @@ fn main() {
|
|||
target_view: None,
|
||||
},
|
||||
Material::new(math::vec4(0.5, 0.3, 0.3, 1.0)),
|
||||
// _cube_handle.clone(),
|
||||
LocalToWorld::identity(),
|
||||
Translation::new(4.0, -4.0, 5.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(),
|
||||
// )
|
||||
// ]);
|
||||
]);
|
||||
|
||||
// camera
|
||||
world.insert((), vec![
|
||||
|
||||
// camera
|
||||
(
|
||||
Camera::new(CameraType::Projection {
|
||||
fov: std::f32::consts::PI / 4.0,
|
||||
|
@ -256,114 +71,9 @@ fn main() {
|
|||
}),
|
||||
ActiveCamera,
|
||||
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, 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::{
|
||||
event,
|
||||
event::WindowEvent,
|
||||
|
@ -7,30 +13,27 @@ use winit::{
|
|||
|
||||
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 window: Window,
|
||||
pub window: Option<Window>,
|
||||
pub render_graph: RenderGraph,
|
||||
pub scheduler: SystemScheduler<ApplicationStage>,
|
||||
pub swap_chain: Option<wgpu::SwapChain>,
|
||||
pub scheduler: SystemScheduler<AppStage>,
|
||||
}
|
||||
|
||||
impl Application {
|
||||
fn add_default_passes(&mut self) {
|
||||
self.render_graph.add_render_resource_manager(Box::new(render_resources::MaterialResourceManager));
|
||||
self.render_graph.add_render_resource_manager(Box::new(render_resources::LightResourceManager::new(10)));
|
||||
self.render_graph.add_render_resource_manager(Box::new(render_resources::GlobalResourceManager));
|
||||
self.render_graph.add_render_resource_manager(Box::new(render_resources::Global2dResourceManager));
|
||||
|
||||
let depth_format = wgpu::TextureFormat::Depth32Float;
|
||||
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()));
|
||||
}
|
||||
impl App {
|
||||
pub fn new(world: World, scheduler: SystemScheduler<AppStage>) -> App {
|
||||
App {
|
||||
world: world,
|
||||
scheduler: scheduler,
|
||||
render_graph: RenderGraph::new(),
|
||||
swap_chain: None,
|
||||
window: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self) {
|
||||
{
|
||||
|
@ -47,7 +50,7 @@ impl Application {
|
|||
|
||||
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)
|
||||
|
@ -56,11 +59,10 @@ impl Application {
|
|||
|
||||
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(universe: Universe, mut world: World, system_scheduler: SystemScheduler<ApplicationStage>) {
|
||||
pub fn run(mut self) {
|
||||
env_logger::init();
|
||||
let event_loop = EventLoop::new();
|
||||
log::info!("Initializing the window...");
|
||||
|
@ -80,14 +82,14 @@ impl Application {
|
|||
limits: wgpu::Limits::default(),
|
||||
});
|
||||
|
||||
let (window, hidpi_factor, size, surface) = {
|
||||
let (window, size, surface) = {
|
||||
let window = winit::window::Window::new(&event_loop).unwrap();
|
||||
window.set_title("bevy");
|
||||
window.set_inner_size((1280, 720).into());
|
||||
let hidpi_factor = window.hidpi_factor();
|
||||
let size = window.inner_size().to_physical(hidpi_factor);
|
||||
let surface = wgpu::Surface::create(&window);
|
||||
(window, hidpi_factor, size, surface)
|
||||
(window, size, surface)
|
||||
};
|
||||
|
||||
let swap_chain_descriptor = wgpu::SwapChainDescriptor {
|
||||
|
@ -98,21 +100,12 @@ impl Application {
|
|||
present_mode: wgpu::PresentMode::Vsync,
|
||||
};
|
||||
let swap_chain = device.create_swap_chain(&surface, &swap_chain_descriptor);
|
||||
|
||||
world.resources.insert(Time::new());
|
||||
|
||||
log::info!("Initializing the example...");
|
||||
let render_graph = RenderGraph::new(device, swap_chain_descriptor, swap_chain, queue, surface);
|
||||
let mut app = Application {
|
||||
universe,
|
||||
world,
|
||||
window,
|
||||
render_graph,
|
||||
scheduler: system_scheduler,
|
||||
};
|
||||
self.render_graph.initialize(&mut self.world, device, swap_chain_descriptor, queue, surface);
|
||||
self.window = Some(window);
|
||||
self.swap_chain = Some(swap_chain);
|
||||
|
||||
app.add_default_passes();
|
||||
app.render_graph.initialize(&mut app.world);
|
||||
|
||||
log::info!("Entering render loop...");
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
|
@ -126,11 +119,12 @@ impl Application {
|
|||
event: WindowEvent::Resized(size),
|
||||
..
|
||||
} => {
|
||||
let hidpi_factor = self.window.as_ref().unwrap().hidpi_factor();
|
||||
let physical = size.to_physical(hidpi_factor);
|
||||
log::info!("Resizing to {:?}", physical);
|
||||
let width = physical.width.round() as u32;
|
||||
let height = physical.height.round() as u32;
|
||||
app.resize(width, height);
|
||||
self.resize(width, height);
|
||||
}
|
||||
event::Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::KeyboardInput {
|
||||
|
@ -146,11 +140,11 @@ impl Application {
|
|||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
_ => {
|
||||
app.handle_event(event);
|
||||
self.handle_event(event);
|
||||
}
|
||||
},
|
||||
event::Event::EventsCleared => {
|
||||
app.update();
|
||||
self.update();
|
||||
}
|
||||
_ => (),
|
||||
}
|
|
@ -1,21 +1,2 @@
|
|||
use legion::schedule::Stage;
|
||||
|
||||
pub mod 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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use time::Time;
|
|
@ -1,10 +1,10 @@
|
|||
pub mod render;
|
||||
pub mod asset;
|
||||
mod application;
|
||||
mod app;
|
||||
mod vertex;
|
||||
mod core;
|
||||
|
||||
pub use application::Application;
|
||||
pub use app::{App, AppStage, AppBuilder};
|
||||
pub use crate::core::*;
|
||||
|
||||
pub use wgpu;
|
||||
|
|
|
@ -24,6 +24,10 @@ impl ForwardInstancedPipeline {
|
|||
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 entities_count = entities.iter_immutable(world).count();
|
||||
if entities_count == 0 {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let size = mem::size_of::<SimpleMaterialUniforms>();
|
||||
|
||||
// TODO: use a staging buffer for more efficient gpu reads
|
||||
|
|
|
@ -33,6 +33,10 @@ impl UiPipeline {
|
|||
let mut rect_query = <Read<Rect>>::query();
|
||||
let rect_count = rect_query.iter_immutable(world).count();
|
||||
|
||||
if rect_count == 0 {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut data = Vec::with_capacity(rect_count);
|
||||
// TODO: this probably isn't the best way to handle z-ordering
|
||||
let mut z = 0.9999;
|
||||
|
|
|
@ -11,12 +11,11 @@ use std::collections::HashMap;
|
|||
use legion::world::World;
|
||||
|
||||
pub struct RenderGraph {
|
||||
pub data: RenderGraphData,
|
||||
pub data: Option<RenderGraphData>,
|
||||
passes: HashMap<String, Box<dyn Pass>>,
|
||||
pipelines: HashMap<String, Box<dyn Pipeline>>,
|
||||
pass_pipelines: HashMap<String, Vec<String>>,
|
||||
render_resource_managers: Vec<Box<dyn RenderResourceManager>>,
|
||||
pub swap_chain: wgpu::SwapChain, // TODO: this is weird
|
||||
}
|
||||
|
||||
pub struct RenderGraphData {
|
||||
|
@ -77,53 +76,56 @@ impl RenderGraphData {
|
|||
}
|
||||
|
||||
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 {
|
||||
passes: HashMap::new(),
|
||||
pipelines: HashMap::new(),
|
||||
swap_chain,
|
||||
pass_pipelines: HashMap::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() {
|
||||
render_resource_manager.initialize(&mut self.data, world);
|
||||
render_resource_manager.initialize(&mut data, world);
|
||||
}
|
||||
|
||||
for pass in self.passes.values_mut() {
|
||||
pass.initialize(&mut self.data);
|
||||
pass.initialize(&mut data);
|
||||
}
|
||||
|
||||
for pipeline in self.pipelines.values_mut() {
|
||||
pipeline.initialize(&mut self.data, world);
|
||||
pipeline.initialize(&mut data, world);
|
||||
}
|
||||
|
||||
self.data = Some(data);
|
||||
}
|
||||
|
||||
pub fn render(&mut self, world: &mut World) {
|
||||
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()
|
||||
.expect("Timeout when acquiring next swap chain texture");
|
||||
|
||||
let data = self.data.as_mut().unwrap();
|
||||
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() {
|
||||
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() {
|
||||
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 {
|
||||
// TODO: assign pipelines to specific passes
|
||||
if let Some(pipeline_names) = self.pass_pipelines.get(pass_name) {
|
||||
for pipeline_name in pipeline_names.iter() {
|
||||
let pipeline = self.pipelines.get_mut(pipeline_name).unwrap();
|
||||
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();
|
||||
self.data.queue.submit(&[command_buffer]);
|
||||
data.queue.submit(&[command_buffer]);
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, width: u32, height: u32, world: &mut World) {
|
||||
self.data.swap_chain_descriptor.width = width;
|
||||
self.data.swap_chain_descriptor.height = height;
|
||||
self.swap_chain = self.data.device.create_swap_chain(&self.data.surface, &self.data.swap_chain_descriptor);
|
||||
pub fn resize(&mut self, width: u32, height: u32, world: &mut World) -> wgpu::SwapChain {
|
||||
let data = self.data.as_mut().unwrap();
|
||||
data.swap_chain_descriptor.width = width;
|
||||
data.swap_chain_descriptor.height = height;
|
||||
let swap_chain = data.device.create_swap_chain(&data.surface, &data.swap_chain_descriptor);
|
||||
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() {
|
||||
render_resource_manager.resize(&mut self.data, &mut encoder, world);
|
||||
render_resource_manager.resize(data, &mut encoder, world);
|
||||
}
|
||||
|
||||
let command_buffer = encoder.finish();
|
||||
|
||||
for pass in self.passes.values_mut() {
|
||||
pass.resize(&mut self.data);
|
||||
pass.resize(data);
|
||||
}
|
||||
|
||||
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>) {
|
||||
|
|
|
@ -42,6 +42,10 @@ impl RenderResourceManager for LightResourceManager {
|
|||
let mut light_query = <(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
|
||||
let light_count = light_query.iter(world).count();
|
||||
|
||||
if light_count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
self.lights_are_dirty = false;
|
||||
let size = mem::size_of::<LightRaw>();
|
||||
let total_size = size * light_count;
|
||||
|
|
|
@ -26,6 +26,10 @@ impl RenderResourceManager for MaterialResourceManager {
|
|||
let mut entities = <(Write<Material>, Read<LocalToWorld>)>::query()
|
||||
.filter(!component::<Instanced>());
|
||||
let entities_count = entities.iter(world).count();
|
||||
if entities_count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let size = mem::size_of::<MaterialUniforms>();
|
||||
let temp_buf_data = render_graph.device
|
||||
.create_buffer_mapped(entities_count * size, wgpu::BufferUsage::COPY_SRC);
|
||||
|
|
Loading…
Reference in a new issue