mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
remove old render graph
This commit is contained in:
parent
acebeb924c
commit
6f376b5f3f
93 changed files with 524 additions and 3421 deletions
|
@ -1,7 +1,7 @@
|
|||
use bevy::{
|
||||
prelude::*,
|
||||
render::{
|
||||
render_graph_2::{PipelineDescriptor, StandardMaterial, resource_name, resource_providers::UniformResourceProvider},
|
||||
render_graph::{PipelineDescriptor, resource_name},
|
||||
Shader, ShaderStage, Vertex,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ use bevy::prelude::*;
|
|||
|
||||
fn main() {
|
||||
AppBuilder::new()
|
||||
.add_defaults_legacy()
|
||||
.add_defaults()
|
||||
.setup_world(setup)
|
||||
.run();
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ struct Wander {
|
|||
|
||||
fn main() {
|
||||
AppBuilder::new()
|
||||
.add_defaults_legacy()
|
||||
.setup_world(setup)
|
||||
.add_system(build_wander_system())
|
||||
.add_system(build_navigate_system())
|
||||
|
|
|
@ -2,5 +2,5 @@ use bevy::{asset, prelude::*};
|
|||
|
||||
fn main() {
|
||||
asset::load_gltf("examples/assets/Box.gltf").unwrap();
|
||||
AppBuilder::new().add_defaults_legacy().run();
|
||||
AppBuilder::new().add_defaults().run();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ struct Rotator;
|
|||
|
||||
fn main() {
|
||||
AppBuilder::new()
|
||||
.add_defaults_legacy()
|
||||
.add_defaults()
|
||||
.setup_world(setup)
|
||||
.add_system(build_rotator_system())
|
||||
.run();
|
||||
|
|
|
@ -2,7 +2,7 @@ use bevy::prelude::*;
|
|||
|
||||
fn main() {
|
||||
AppBuilder::new()
|
||||
.add_defaults_legacy()
|
||||
.add_defaults()
|
||||
.load_plugin("examples/plugin_loading/example_plugin/target/release/libexample_plugin.so")
|
||||
.run();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||
use type_uuid::TypeUuid;
|
||||
fn main() {
|
||||
let app = AppBuilder::new()
|
||||
.add_defaults_legacy()
|
||||
.add_defaults()
|
||||
.setup_world(setup)
|
||||
.build();
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use bevy::prelude::*;
|
||||
|
||||
fn main() {
|
||||
AppBuilder::new()
|
||||
.add_defaults_legacy()
|
||||
.setup_world(setup)
|
||||
.run();
|
||||
AppBuilder::new().add_defaults().setup_world(setup).run();
|
||||
}
|
||||
|
||||
fn setup(world: &mut World) {
|
||||
|
@ -19,18 +16,33 @@ fn setup(world: &mut World) {
|
|||
world
|
||||
.build()
|
||||
// plane
|
||||
.add_archetype(MeshEntity {
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: plane_handle.clone(),
|
||||
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(0.0, 0.0, 0.0),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.1, 0.2, 0.1, 1.0),
|
||||
everything_is_red: false,
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
// cube
|
||||
.add_archetype(MeshEntity {
|
||||
mesh: cube_handle,
|
||||
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
// tan cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.5, 0.4, 0.3, 1.0),
|
||||
everything_is_red: false,
|
||||
},
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// red cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.5, 0.4, 0.3, 1.0),
|
||||
everything_is_red: true,
|
||||
},
|
||||
translation: Translation::new(3.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.add_archetype(LightEntity {
|
||||
|
@ -38,7 +50,7 @@ fn setup(world: &mut World) {
|
|||
color: wgpu::Color {
|
||||
r: 0.8,
|
||||
g: 0.8,
|
||||
b: 0.5,
|
||||
b: 0.8,
|
||||
a: 1.0,
|
||||
},
|
||||
fov: f32::to_radians(60.0),
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
use bevy::prelude::*;
|
||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||
use std::collections::VecDeque;
|
||||
fn main() {
|
||||
AppBuilder::new()
|
||||
.add_defaults_legacy()
|
||||
.add_system(build_move_system())
|
||||
.add_system(build_print_status_system())
|
||||
.setup_world(setup)
|
||||
.run();
|
||||
}
|
||||
|
||||
fn build_move_system() -> Box<dyn Schedulable> {
|
||||
SystemBuilder::new("Move")
|
||||
.read_resource::<Time>()
|
||||
.with_query(<(Write<Translation>, Write<Material>)>::query())
|
||||
.build(move |_, world, time, person_query| {
|
||||
for (mut translation, mut _material) in person_query.iter_mut(world) {
|
||||
translation.0 += math::vec3(1.0, 0.0, 0.0) * 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>()
|
||||
.build(move |_, _world, time, _queries| {
|
||||
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 {
|
||||
if frame_time_count > 0 && frame_time_total > 0.0 {
|
||||
println!(
|
||||
"fps: {}",
|
||||
1.0 / (frame_time_total / frame_time_count as f32)
|
||||
)
|
||||
}
|
||||
elapsed = 0.0;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn setup(world: &mut World) {
|
||||
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>>().unwrap();
|
||||
(mesh_storage.add(cube), mesh_storage.add(plane))
|
||||
};
|
||||
|
||||
let mut builder = world
|
||||
.build()
|
||||
// plane
|
||||
.add_archetype(MeshEntity {
|
||||
mesh: plane_handle.clone(),
|
||||
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(0.0, 0.0, 0.0),
|
||||
})
|
||||
// cube
|
||||
.add_archetype(MeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
})
|
||||
// light
|
||||
.add_archetype(LightEntity {
|
||||
light: 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,
|
||||
},
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(4.0, -4.0, 5.0),
|
||||
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||
})
|
||||
// camera
|
||||
.add_archetype(CameraEntity {
|
||||
camera: Camera::new(CameraType::Projection {
|
||||
fov: std::f32::consts::PI / 4.0,
|
||||
near: 1.0,
|
||||
far: 1000.0,
|
||||
aspect_ratio: 1.0,
|
||||
}),
|
||||
active_camera: ActiveCamera,
|
||||
local_to_world: LocalToWorld(Mat4::look_at_rh(
|
||||
Vec3::new(3.0, 8.0, 5.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..10000 {
|
||||
builder = builder.add_archetype(MeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(
|
||||
rng.gen_range(-50.0, 50.0),
|
||||
rng.gen_range(-50.0, 50.0),
|
||||
0.0,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
builder.build()
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
use bevy::{prelude::*, render::render_graph_2::StandardMaterial};
|
||||
|
||||
fn main() {
|
||||
AppBuilder::new().add_defaults().setup_world(setup).run();
|
||||
}
|
||||
|
||||
fn setup(world: &mut World) {
|
||||
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>>().unwrap();
|
||||
(mesh_storage.add(cube), mesh_storage.add(plane))
|
||||
};
|
||||
|
||||
world
|
||||
.build()
|
||||
// plane
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: plane_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.1, 0.2, 0.1, 1.0),
|
||||
everything_is_red: false,
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
// tan cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.5, 0.4, 0.3, 1.0),
|
||||
everything_is_red: false,
|
||||
},
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// red cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.5, 0.4, 0.3, 1.0),
|
||||
everything_is_red: true,
|
||||
},
|
||||
translation: Translation::new(3.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.add_archetype(LightEntity {
|
||||
light: Light {
|
||||
color: wgpu::Color {
|
||||
r: 0.8,
|
||||
g: 0.8,
|
||||
b: 0.8,
|
||||
a: 1.0,
|
||||
},
|
||||
fov: f32::to_radians(60.0),
|
||||
depth: 0.1..50.0,
|
||||
target_view: None,
|
||||
},
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(4.0, -4.0, 5.0),
|
||||
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||
})
|
||||
// camera
|
||||
.add_archetype(CameraEntity {
|
||||
camera: Camera::new(CameraType::Projection {
|
||||
fov: std::f32::consts::PI / 4.0,
|
||||
near: 1.0,
|
||||
far: 1000.0,
|
||||
aspect_ratio: 1.0,
|
||||
}),
|
||||
active_camera: ActiveCamera,
|
||||
local_to_world: LocalToWorld(Mat4::look_at_rh(
|
||||
Vec3::new(3.0, 8.0, 5.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 0.0, 1.0),
|
||||
)),
|
||||
})
|
||||
.build();
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use bevy::{prelude::*, render::render_graph_2::StandardMaterial};
|
||||
use bevy::prelude::*;
|
||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||
use std::collections::VecDeque;
|
||||
|
|
@ -1,41 +1,36 @@
|
|||
use bevy::{asset, prelude::*};
|
||||
|
||||
fn main() {
|
||||
AppBuilder::new()
|
||||
.add_defaults_legacy()
|
||||
.setup_world(setup)
|
||||
.run();
|
||||
AppBuilder::new().add_defaults().setup_world(setup).run();
|
||||
}
|
||||
|
||||
fn setup(world: &mut World) {
|
||||
let cube_handle = {
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let cube = Mesh::load(MeshType::Cube);
|
||||
mesh_storage.add(cube)
|
||||
mesh_storage.add(Mesh::load(MeshType::Cube))
|
||||
};
|
||||
|
||||
let texture_handle = {
|
||||
let _texture_handle = {
|
||||
let mut texture_storage = world.resources.get_mut::<AssetStorage<Texture>>().unwrap();
|
||||
let texture = Texture::load(TextureType::Data(asset::create_texels(256)));
|
||||
texture_storage.add(texture)
|
||||
};
|
||||
|
||||
// cube
|
||||
world.insert(
|
||||
(),
|
||||
vec![(
|
||||
cube_handle,
|
||||
Material::new(Albedo::Texture(texture_handle)),
|
||||
LocalToWorld::identity(),
|
||||
Translation::new(0.0, 0.0, 1.0),
|
||||
)],
|
||||
);
|
||||
|
||||
// light
|
||||
world.insert(
|
||||
(),
|
||||
vec![(
|
||||
Light {
|
||||
world
|
||||
.build()
|
||||
// cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
|
||||
everything_is_red: false,
|
||||
},
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.add_archetype(LightEntity {
|
||||
light: Light {
|
||||
color: wgpu::Color {
|
||||
r: 0.8,
|
||||
g: 0.8,
|
||||
|
@ -46,28 +41,24 @@ fn setup(world: &mut World) {
|
|||
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),
|
||||
)],
|
||||
);
|
||||
|
||||
// camera
|
||||
world.insert(
|
||||
(),
|
||||
vec![(
|
||||
Camera::new(CameraType::Projection {
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(4.0, -4.0, 5.0),
|
||||
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||
})
|
||||
// camera
|
||||
.add_archetype(CameraEntity {
|
||||
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(
|
||||
active_camera: ActiveCamera,
|
||||
local_to_world: LocalToWorld(Mat4::look_at_rh(
|
||||
Vec3::new(3.0, 8.0, 5.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 0.0, 1.0),
|
||||
)),
|
||||
)],
|
||||
);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
use bevy::{asset, prelude::*, render::render_graph_2::StandardMaterial};
|
||||
|
||||
fn main() {
|
||||
AppBuilder::new().add_defaults().setup_world(setup).run();
|
||||
}
|
||||
|
||||
fn setup(world: &mut World) {
|
||||
let cube_handle = {
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
mesh_storage.add(Mesh::load(MeshType::Cube))
|
||||
};
|
||||
|
||||
let _texture_handle = {
|
||||
let mut texture_storage = world.resources.get_mut::<AssetStorage<Texture>>().unwrap();
|
||||
let texture = Texture::load(TextureType::Data(asset::create_texels(256)));
|
||||
texture_storage.add(texture)
|
||||
};
|
||||
|
||||
world
|
||||
.build()
|
||||
// cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
|
||||
everything_is_red: false,
|
||||
},
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.add_archetype(LightEntity {
|
||||
light: 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,
|
||||
},
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(4.0, -4.0, 5.0),
|
||||
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||
})
|
||||
// camera
|
||||
.add_archetype(CameraEntity {
|
||||
camera: Camera::new(CameraType::Projection {
|
||||
fov: std::f32::consts::PI / 4.0,
|
||||
near: 1.0,
|
||||
far: 1000.0,
|
||||
aspect_ratio: 1.0,
|
||||
}),
|
||||
active_camera: ActiveCamera,
|
||||
local_to_world: LocalToWorld(Mat4::look_at_rh(
|
||||
Vec3::new(3.0, 8.0, 5.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 0.0, 1.0),
|
||||
)),
|
||||
})
|
||||
.build();
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
use bevy::prelude::*;
|
||||
|
||||
fn main() {
|
||||
AppBuilder::new()
|
||||
.add_defaults_legacy()
|
||||
.setup_world(setup)
|
||||
.run();
|
||||
AppBuilder::new().add_defaults().setup_world(setup).run();
|
||||
}
|
||||
|
||||
fn setup(world: &mut World) {
|
||||
|
@ -14,21 +11,21 @@ fn setup(world: &mut World) {
|
|||
mesh_storage.add(cube)
|
||||
};
|
||||
|
||||
// cube
|
||||
world.insert(
|
||||
(),
|
||||
vec![(
|
||||
cube_handle,
|
||||
LocalToWorld::identity(),
|
||||
Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
||||
)],
|
||||
);
|
||||
|
||||
// light
|
||||
world.insert(
|
||||
(),
|
||||
vec![(
|
||||
Light {
|
||||
world
|
||||
.build()
|
||||
// cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
|
||||
everything_is_red: false,
|
||||
},
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.add_archetype(LightEntity {
|
||||
light: Light {
|
||||
color: wgpu::Color {
|
||||
r: 0.8,
|
||||
g: 0.8,
|
||||
|
@ -39,39 +36,28 @@ fn setup(world: &mut World) {
|
|||
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),
|
||||
)],
|
||||
);
|
||||
|
||||
// 3d camera
|
||||
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),
|
||||
)),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
// 2d camera
|
||||
world.insert(
|
||||
(),
|
||||
vec![(
|
||||
Camera::new(CameraType::Orthographic {
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(4.0, -4.0, 5.0),
|
||||
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||
})
|
||||
// 3d camera
|
||||
.add_archetype(CameraEntity {
|
||||
camera: Camera::new(CameraType::Projection {
|
||||
fov: std::f32::consts::PI / 4.0,
|
||||
near: 1.0,
|
||||
far: 1000.0,
|
||||
aspect_ratio: 1.0,
|
||||
}),
|
||||
active_camera: ActiveCamera,
|
||||
local_to_world: LocalToWorld(Mat4::look_at_rh(
|
||||
Vec3::new(3.0, 8.0, 5.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 0.0, 1.0),
|
||||
)),
|
||||
})
|
||||
// 2d camera
|
||||
.add_archetype(Camera2dEntity {
|
||||
camera: Camera::new(CameraType::Orthographic {
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
bottom: 0.0,
|
||||
|
@ -79,9 +65,9 @@ fn setup(world: &mut World) {
|
|||
near: 0.0,
|
||||
far: 1.0,
|
||||
}),
|
||||
ActiveCamera2d,
|
||||
)],
|
||||
);
|
||||
active_camera_2d: ActiveCamera2d,
|
||||
})
|
||||
.build();
|
||||
|
||||
// bottom left anchor with vertical fill
|
||||
world.insert(
|
||||
|
|
|
@ -1,172 +0,0 @@
|
|||
use bevy::{prelude::*, render::render_graph_2::StandardMaterial};
|
||||
|
||||
fn main() {
|
||||
AppBuilder::new().add_defaults().setup_world(setup).run();
|
||||
}
|
||||
|
||||
fn setup(world: &mut World) {
|
||||
let cube = Mesh::load(MeshType::Cube);
|
||||
let cube_handle = {
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
mesh_storage.add(cube)
|
||||
};
|
||||
|
||||
world
|
||||
.build()
|
||||
// cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
|
||||
everything_is_red: false,
|
||||
},
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.add_archetype(LightEntity {
|
||||
light: 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,
|
||||
},
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(4.0, -4.0, 5.0),
|
||||
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||
})
|
||||
// 3d camera
|
||||
.add_archetype(CameraEntity {
|
||||
camera: Camera::new(CameraType::Projection {
|
||||
fov: std::f32::consts::PI / 4.0,
|
||||
near: 1.0,
|
||||
far: 1000.0,
|
||||
aspect_ratio: 1.0,
|
||||
}),
|
||||
active_camera: ActiveCamera,
|
||||
local_to_world: LocalToWorld(Mat4::look_at_rh(
|
||||
Vec3::new(3.0, 8.0, 5.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 0.0, 1.0),
|
||||
)),
|
||||
})
|
||||
// 2d camera
|
||||
.add_archetype(Camera2dEntity {
|
||||
camera: Camera::new(CameraType::Orthographic {
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
bottom: 0.0,
|
||||
top: 0.0,
|
||||
near: 0.0,
|
||||
far: 1.0,
|
||||
}),
|
||||
active_camera_2d: ActiveCamera2d,
|
||||
})
|
||||
.build();
|
||||
|
||||
// bottom left anchor with vertical fill
|
||||
world.insert(
|
||||
(),
|
||||
vec![(Node::new(
|
||||
math::vec2(0.0, 0.0),
|
||||
Anchors::new(0.0, 0.0, 0.0, 1.0),
|
||||
Margins::new(10.0, 200.0, 10.0, 10.0),
|
||||
math::vec4(0.1, 0.1, 0.1, 1.0),
|
||||
),)],
|
||||
);
|
||||
|
||||
// top right anchor with vertical fill
|
||||
world.insert(
|
||||
(),
|
||||
vec![(Node::new(
|
||||
math::vec2(0.0, 0.0),
|
||||
Anchors::new(1.0, 1.0, 0.0, 1.0),
|
||||
Margins::new(10.0, 100.0, 50.0, 100.0),
|
||||
math::vec4(0.1, 0.1, 0.1, 1.0),
|
||||
),)],
|
||||
);
|
||||
|
||||
// render order test: reddest in the back, whitest in the front
|
||||
world.insert(
|
||||
(),
|
||||
vec![(Node::new(
|
||||
math::vec2(75.0, 75.0),
|
||||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
math::vec4(1.0, 0.1, 0.1, 1.0),
|
||||
),)],
|
||||
);
|
||||
|
||||
world.insert(
|
||||
(),
|
||||
vec![(Node::new(
|
||||
math::vec2(50.0, 50.0),
|
||||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
math::vec4(1.0, 0.3, 0.3, 1.0),
|
||||
),)],
|
||||
);
|
||||
|
||||
world.insert(
|
||||
(),
|
||||
vec![(Node::new(
|
||||
math::vec2(100.0, 100.0),
|
||||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
math::vec4(1.0, 0.5, 0.5, 1.0),
|
||||
),)],
|
||||
);
|
||||
|
||||
world.insert(
|
||||
(),
|
||||
vec![(Node::new(
|
||||
math::vec2(150.0, 150.0),
|
||||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
math::vec4(1.0, 0.7, 0.7, 1.0),
|
||||
),)],
|
||||
);
|
||||
|
||||
// parenting
|
||||
let parent = *world
|
||||
.insert(
|
||||
(),
|
||||
vec![(Node::new(
|
||||
math::vec2(300.0, 300.0),
|
||||
Anchors::new(0.0, 0.0, 0.0, 0.0),
|
||||
Margins::new(0.0, 200.0, 0.0, 200.0),
|
||||
math::vec4(0.1, 0.1, 1.0, 1.0),
|
||||
),)],
|
||||
)
|
||||
.first()
|
||||
.unwrap();
|
||||
|
||||
world.insert(
|
||||
(),
|
||||
vec![(
|
||||
Node::new(
|
||||
math::vec2(0.0, 0.0),
|
||||
Anchors::new(0.0, 1.0, 0.0, 1.0),
|
||||
Margins::new(20.0, 20.0, 20.0, 20.0),
|
||||
math::vec4(0.6, 0.6, 1.0, 1.0),
|
||||
),
|
||||
Parent(parent),
|
||||
)],
|
||||
);
|
||||
|
||||
// alpha test
|
||||
world.insert(
|
||||
(),
|
||||
vec![(Node::new(
|
||||
math::vec2(200.0, 200.0),
|
||||
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||
math::vec4(1.0, 0.9, 0.9, 0.4),
|
||||
),)],
|
||||
);
|
||||
}
|
|
@ -9,14 +9,12 @@ use legion::prelude::*;
|
|||
use crate::{
|
||||
app::AppBuilder,
|
||||
core::Time,
|
||||
render,
|
||||
render::render_graph_2::{RenderGraph, Renderer},
|
||||
render::render_graph::{RenderGraph, Renderer},
|
||||
};
|
||||
|
||||
pub struct App {
|
||||
pub universe: Universe,
|
||||
pub world: World,
|
||||
pub legacy_render_graph: Option<render::RenderGraph>,
|
||||
pub renderer: Option<Box<dyn Renderer>>,
|
||||
pub render_graph: RenderGraph,
|
||||
pub schedule: Schedule,
|
||||
|
@ -27,7 +25,6 @@ impl App {
|
|||
universe: Universe,
|
||||
world: World,
|
||||
schedule: Schedule,
|
||||
legacy_render_graph: Option<render::RenderGraph>,
|
||||
renderer: Option<Box<dyn Renderer>>,
|
||||
render_graph: RenderGraph,
|
||||
) -> App {
|
||||
|
@ -35,7 +32,6 @@ impl App {
|
|||
universe,
|
||||
world,
|
||||
schedule,
|
||||
legacy_render_graph,
|
||||
renderer,
|
||||
render_graph,
|
||||
}
|
||||
|
@ -51,11 +47,6 @@ impl App {
|
|||
}
|
||||
self.schedule.execute(&mut self.world);
|
||||
|
||||
// TODO: remove me
|
||||
if let Some(ref mut render_graph) = self.legacy_render_graph {
|
||||
render_graph.render(&mut self.world);
|
||||
}
|
||||
|
||||
if let Some(ref mut renderer) = self.renderer {
|
||||
renderer.process_render_graph(&mut self.render_graph, &mut self.world);
|
||||
}
|
||||
|
@ -79,9 +70,6 @@ impl App {
|
|||
self.world.resources.insert(window);
|
||||
|
||||
log::info!("Initializing the example...");
|
||||
if let Some(ref mut render_graph) = self.legacy_render_graph {
|
||||
render_graph.initialize(&mut self.world);
|
||||
}
|
||||
|
||||
if let Some(ref mut renderer) = self.renderer {
|
||||
renderer.initialize(&mut self.world, &mut self.render_graph);
|
||||
|
@ -99,10 +87,6 @@ impl App {
|
|||
event: WindowEvent::Resized(size),
|
||||
..
|
||||
} => {
|
||||
if let Some(ref mut render_graph) = self.legacy_render_graph {
|
||||
render_graph.resize(size.width, size.height, &mut self.world);
|
||||
}
|
||||
|
||||
if let Some(ref mut renderer) = self.renderer {
|
||||
renderer.resize(
|
||||
&mut self.world,
|
||||
|
|
|
@ -5,10 +5,10 @@ use crate::{
|
|||
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
|
||||
plugin::load_plugin,
|
||||
render::{
|
||||
passes::*,
|
||||
render_graph_2::{
|
||||
passes::*, pipelines::*, renderers::wgpu_renderer::WgpuRenderer, resource_providers::*,
|
||||
ShaderPipelineAssignments, StandardMaterial, RenderGraphBuilder
|
||||
render_graph::{
|
||||
draw_targets::*, passes::*, pipelines::*, renderers::wgpu_renderer::WgpuRenderer,
|
||||
resource_name, resource_providers::*, CompiledShaderMap, PipelineDescriptor,
|
||||
RenderGraphBuilder, Renderer, ShaderPipelineAssignments, StandardMaterial,
|
||||
},
|
||||
*,
|
||||
},
|
||||
|
@ -16,15 +16,13 @@ use crate::{
|
|||
};
|
||||
|
||||
use bevy_transform::{prelude::LocalToWorld, transform_system_bundle};
|
||||
use render_graph_2::{CompiledShaderMap, PipelineDescriptor, resource_name, draw_targets::{ui_draw_target, meshes_draw_target, assigned_meshes_draw_target}};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct AppBuilder {
|
||||
pub world: World,
|
||||
pub universe: Universe,
|
||||
pub legacy_render_graph: Option<RenderGraph>,
|
||||
pub renderer: Option<Box<dyn render_graph_2::Renderer>>,
|
||||
pub render_graph_builder: render_graph_2::RenderGraphBuilder,
|
||||
pub renderer: Option<Box<dyn Renderer>>,
|
||||
pub render_graph_builder: RenderGraphBuilder,
|
||||
pub system_stages: HashMap<String, Vec<Box<dyn Schedulable>>>,
|
||||
pub runnable_stages: HashMap<String, Vec<Box<dyn Runnable>>>,
|
||||
pub stage_order: Vec<String>,
|
||||
|
@ -37,8 +35,7 @@ impl AppBuilder {
|
|||
AppBuilder {
|
||||
universe,
|
||||
world,
|
||||
render_graph_builder: render_graph_2::RenderGraphBuilder::new(),
|
||||
legacy_render_graph: None,
|
||||
render_graph_builder: RenderGraphBuilder::new(),
|
||||
renderer: None,
|
||||
system_stages: HashMap::new(),
|
||||
runnable_stages: HashMap::new(),
|
||||
|
@ -70,7 +67,6 @@ impl AppBuilder {
|
|||
self.universe,
|
||||
self.world,
|
||||
schedule_builder.build(),
|
||||
self.legacy_render_graph,
|
||||
self.renderer,
|
||||
self.render_graph_builder.build(),
|
||||
)
|
||||
|
@ -120,46 +116,6 @@ impl AppBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_legacy_render_graph(mut self) -> Self {
|
||||
self.legacy_render_graph = Some(RenderGraph::new());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_default_passes(mut self) -> Self {
|
||||
let msaa_samples = 4;
|
||||
{
|
||||
let render_graph = &mut self.legacy_render_graph.as_mut().unwrap();
|
||||
render_graph
|
||||
.add_render_resource_manager(Box::new(render_resources::MaterialResourceManager));
|
||||
render_graph.add_render_resource_manager(Box::new(
|
||||
render_resources::LightResourceManager::new(10),
|
||||
));
|
||||
render_graph
|
||||
.add_render_resource_manager(Box::new(render_resources::GlobalResourceManager));
|
||||
render_graph
|
||||
.add_render_resource_manager(Box::new(render_resources::Global2dResourceManager));
|
||||
|
||||
let depth_format = wgpu::TextureFormat::Depth32Float;
|
||||
render_graph.set_pass(
|
||||
"forward",
|
||||
Box::new(ForwardPass::new(depth_format, msaa_samples)),
|
||||
);
|
||||
render_graph.set_pipeline(
|
||||
"forward",
|
||||
"forward",
|
||||
Box::new(ForwardPipeline::new(msaa_samples)),
|
||||
);
|
||||
render_graph.set_pipeline(
|
||||
"forward",
|
||||
"forward_instanced",
|
||||
Box::new(ForwardInstancedPipeline::new(depth_format, msaa_samples)),
|
||||
);
|
||||
render_graph.set_pipeline("forward", "ui", Box::new(UiPipeline::new(msaa_samples)));
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_default_resources(mut self) -> Self {
|
||||
let resources = &mut self.world.resources;
|
||||
resources.insert(Time::new());
|
||||
|
@ -185,7 +141,10 @@ impl AppBuilder {
|
|||
self.setup_render_graph(|builder, pipeline_storage, shader_storage| {
|
||||
builder
|
||||
.add_draw_target(resource_name::draw_target::MESHES, meshes_draw_target)
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES, assigned_meshes_draw_target)
|
||||
.add_draw_target(
|
||||
resource_name::draw_target::ASSIGNED_MESHES,
|
||||
assigned_meshes_draw_target,
|
||||
)
|
||||
.add_draw_target(resource_name::draw_target::UI, ui_draw_target)
|
||||
.add_resource_provider(Box::new(CameraResourceProvider))
|
||||
.add_resource_provider(Box::new(Camera2dResourceProvider))
|
||||
|
@ -199,7 +158,14 @@ impl AppBuilder {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn setup_render_graph(mut self, setup: impl Fn(RenderGraphBuilder, &mut AssetStorage<PipelineDescriptor>, &mut AssetStorage<Shader>) -> RenderGraphBuilder) -> Self {
|
||||
pub fn setup_render_graph(
|
||||
mut self,
|
||||
setup: impl Fn(
|
||||
RenderGraphBuilder,
|
||||
&mut AssetStorage<PipelineDescriptor>,
|
||||
&mut AssetStorage<Shader>,
|
||||
) -> RenderGraphBuilder,
|
||||
) -> Self {
|
||||
{
|
||||
let mut pipeline_storage = self
|
||||
.world
|
||||
|
@ -211,7 +177,11 @@ impl AppBuilder {
|
|||
.resources
|
||||
.get_mut::<AssetStorage<Shader>>()
|
||||
.unwrap();
|
||||
self.render_graph_builder = setup(self.render_graph_builder, &mut pipeline_storage, &mut shader_storage);
|
||||
self.render_graph_builder = setup(
|
||||
self.render_graph_builder,
|
||||
&mut pipeline_storage,
|
||||
&mut shader_storage,
|
||||
);
|
||||
}
|
||||
|
||||
self
|
||||
|
@ -222,13 +192,6 @@ impl AppBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn add_defaults_legacy(self) -> Self {
|
||||
self.with_legacy_render_graph()
|
||||
.add_default_resources()
|
||||
.add_default_passes()
|
||||
.add_default_systems()
|
||||
}
|
||||
|
||||
pub fn add_defaults(self) -> Self {
|
||||
self.add_default_resources()
|
||||
.add_default_systems()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
prelude::*,
|
||||
render::render_graph_2::{Renderable, ShaderUniforms, StandardMaterial},
|
||||
render::render_graph::{Renderable, ShaderUniforms, StandardMaterial},
|
||||
};
|
||||
use bevy_derive::EntityArchetype;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ pub use crate::{
|
|||
ecs::{default_archetypes::*, EntityArchetype, WorldBuilder, WorldBuilderSource},
|
||||
render::{
|
||||
ActiveCamera, ActiveCamera2d, Albedo, Camera, CameraType, Instanced, Light, Material,
|
||||
render_graph::StandardMaterial,
|
||||
},
|
||||
ui::{Anchors, Margins, Node},
|
||||
};
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
pub mod camera;
|
||||
pub mod instancing;
|
||||
pub mod passes;
|
||||
pub mod render_graph_2;
|
||||
pub mod render_resources;
|
||||
pub mod render_graph;
|
||||
pub mod shader;
|
||||
pub mod shader_reflect;
|
||||
|
||||
mod light;
|
||||
mod material;
|
||||
mod render_graph;
|
||||
mod vertex;
|
||||
|
||||
pub use camera::*;
|
||||
pub use light::*;
|
||||
pub use material::*;
|
||||
pub use render_graph::*;
|
||||
pub use shader::*;
|
||||
|
||||
use std::mem;
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
#version 450
|
||||
|
||||
const int MAX_LIGHTS = 10;
|
||||
|
||||
layout(location = 0) in vec3 v_Normal;
|
||||
layout(location = 1) in vec4 v_Position;
|
||||
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
|
||||
struct Light {
|
||||
mat4 proj;
|
||||
vec4 pos;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform Globals {
|
||||
mat4 ViewProj;
|
||||
uvec4 NumLights;
|
||||
};
|
||||
layout(set = 0, binding = 1) uniform Lights {
|
||||
Light SceneLights[MAX_LIGHTS];
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0) uniform Entity {
|
||||
mat4 World;
|
||||
vec4 Color;
|
||||
};
|
||||
|
||||
void main() {
|
||||
vec3 normal = normalize(v_Normal);
|
||||
vec3 ambient = vec3(0.05, 0.05, 0.05);
|
||||
// accumulate color
|
||||
vec3 color = ambient;
|
||||
for (int i=0; i<int(NumLights.x) && i<MAX_LIGHTS; ++i) {
|
||||
Light light = SceneLights[i];
|
||||
// compute Lambertian diffuse term
|
||||
vec3 light_dir = normalize(light.pos.xyz - v_Position.xyz);
|
||||
float diffuse = max(0.0, dot(normal, light_dir));
|
||||
// add light contribution
|
||||
color += diffuse * light.color.xyz;
|
||||
}
|
||||
// multiply the light by material color
|
||||
o_Target = vec4(color, 1.0) * Color;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 a_Pos;
|
||||
layout(location = 1) in vec4 a_Normal;
|
||||
layout(location = 2) in vec4 a_Uv;
|
||||
|
||||
layout(location = 0) out vec3 v_Normal;
|
||||
layout(location = 1) out vec4 v_Position;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Globals {
|
||||
mat4 ViewProj;
|
||||
uvec4 NumLights;
|
||||
};
|
||||
layout(set = 1, binding = 0) uniform Entity {
|
||||
mat4 World;
|
||||
vec4 Color;
|
||||
};
|
||||
|
||||
void main() {
|
||||
v_Normal = mat3(World) * vec3(a_Normal.xyz);
|
||||
v_Position = World * vec4(a_Pos);
|
||||
gl_Position = ViewProj * v_Position;
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
use crate::render::*;
|
||||
use legion::prelude::*;
|
||||
use wgpu::{Device, SwapChainDescriptor};
|
||||
use zerocopy::{AsBytes, FromBytes};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
pub struct ForwardUniforms {
|
||||
pub proj: [[f32; 4]; 4],
|
||||
pub num_lights: [u32; 4],
|
||||
}
|
||||
|
||||
pub struct ForwardPass {
|
||||
pub depth_format: wgpu::TextureFormat,
|
||||
pub msaa_samples: usize,
|
||||
}
|
||||
|
||||
impl ForwardPass {
|
||||
pub fn new(depth_format: wgpu::TextureFormat, msaa_samples: usize) -> Self {
|
||||
ForwardPass {
|
||||
depth_format,
|
||||
msaa_samples,
|
||||
}
|
||||
}
|
||||
fn get_depth_texture(
|
||||
&self,
|
||||
device: &Device,
|
||||
swap_chain_descriptor: &SwapChainDescriptor,
|
||||
) -> wgpu::TextureView {
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
size: wgpu::Extent3d {
|
||||
width: swap_chain_descriptor.width,
|
||||
height: swap_chain_descriptor.height,
|
||||
depth: 1,
|
||||
},
|
||||
array_layer_count: 1,
|
||||
mip_level_count: 1,
|
||||
sample_count: self.msaa_samples as u32,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: self.depth_format,
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
|
||||
texture.create_default_view()
|
||||
}
|
||||
|
||||
fn get_multisampled_framebuffer(
|
||||
&self,
|
||||
device: &Device,
|
||||
swap_chain_descriptor: &SwapChainDescriptor,
|
||||
sample_count: usize,
|
||||
) -> wgpu::TextureView {
|
||||
let multisampled_texture_extent = wgpu::Extent3d {
|
||||
width: swap_chain_descriptor.width,
|
||||
height: swap_chain_descriptor.height,
|
||||
depth: 1,
|
||||
};
|
||||
let multisampled_frame_descriptor = &wgpu::TextureDescriptor {
|
||||
size: multisampled_texture_extent,
|
||||
array_layer_count: 1,
|
||||
mip_level_count: 1,
|
||||
sample_count: sample_count as u32,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: swap_chain_descriptor.format,
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
};
|
||||
|
||||
device
|
||||
.create_texture(multisampled_frame_descriptor)
|
||||
.create_default_view()
|
||||
}
|
||||
}
|
||||
|
||||
const DEPTH_TEXTURE_NAME: &str = "forward_depth";
|
||||
const MULTISAMPLED_FRAMEBUFFER_TEXTURE_NAME: &str = "forward_multisampled_framebuffer";
|
||||
|
||||
impl Pass for ForwardPass {
|
||||
fn initialize(&self, render_graph: &mut RenderGraphData) {
|
||||
let depth_texture =
|
||||
self.get_depth_texture(&render_graph.device, &render_graph.swap_chain_descriptor);
|
||||
render_graph.set_texture(DEPTH_TEXTURE_NAME, depth_texture);
|
||||
|
||||
if self.msaa_samples > 1 {
|
||||
let multisampled_framebuffer = self.get_multisampled_framebuffer(
|
||||
&render_graph.device,
|
||||
&render_graph.swap_chain_descriptor,
|
||||
self.msaa_samples,
|
||||
);
|
||||
render_graph.set_texture(
|
||||
MULTISAMPLED_FRAMEBUFFER_TEXTURE_NAME,
|
||||
multisampled_framebuffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn begin<'a>(
|
||||
&mut self,
|
||||
render_graph: &mut RenderGraphData,
|
||||
_: &mut World,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
frame: &'a wgpu::SwapChainOutput,
|
||||
) -> Option<wgpu::RenderPass<'a>> {
|
||||
let depth_texture = render_graph.get_texture(DEPTH_TEXTURE_NAME);
|
||||
let color_attachment = if self.msaa_samples == 1 {
|
||||
wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: &frame.view,
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Clear,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 0.3,
|
||||
g: 0.4,
|
||||
b: 0.5,
|
||||
a: 1.0,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
let multisampled_framebuffer = render_graph
|
||||
.get_texture(MULTISAMPLED_FRAMEBUFFER_TEXTURE_NAME)
|
||||
.unwrap();
|
||||
wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: multisampled_framebuffer,
|
||||
resolve_target: Some(&frame.view),
|
||||
load_op: wgpu::LoadOp::Clear,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 0.3,
|
||||
g: 0.4,
|
||||
b: 0.5,
|
||||
a: 1.0,
|
||||
},
|
||||
}
|
||||
};
|
||||
Some(encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[color_attachment],
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: depth_texture.unwrap(),
|
||||
depth_load_op: wgpu::LoadOp::Clear,
|
||||
depth_store_op: wgpu::StoreOp::Store,
|
||||
stencil_load_op: wgpu::LoadOp::Clear,
|
||||
stencil_store_op: wgpu::StoreOp::Store,
|
||||
clear_depth: 1.0,
|
||||
clear_stencil: 0,
|
||||
}),
|
||||
}))
|
||||
}
|
||||
|
||||
fn resize(&self, render_graph: &mut RenderGraphData) {
|
||||
let depth_texture =
|
||||
self.get_depth_texture(&render_graph.device, &render_graph.swap_chain_descriptor);
|
||||
render_graph.set_texture(DEPTH_TEXTURE_NAME, depth_texture);
|
||||
|
||||
if self.msaa_samples > 1 {
|
||||
let multisampled_framebuffer = self.get_multisampled_framebuffer(
|
||||
&render_graph.device,
|
||||
&render_graph.swap_chain_descriptor,
|
||||
self.msaa_samples,
|
||||
);
|
||||
render_graph.set_texture(
|
||||
MULTISAMPLED_FRAMEBUFFER_TEXTURE_NAME,
|
||||
multisampled_framebuffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn should_repeat(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
use crate::{asset::*, render::*};
|
||||
use legion::prelude::*;
|
||||
use wgpu::SwapChainOutput;
|
||||
|
||||
pub struct ForwardPipeline {
|
||||
pub pipeline: Option<wgpu::RenderPipeline>,
|
||||
pub depth_format: wgpu::TextureFormat,
|
||||
pub bind_group: Option<wgpu::BindGroup>,
|
||||
pub msaa_samples: usize,
|
||||
}
|
||||
|
||||
impl ForwardPipeline {
|
||||
pub fn new(msaa_samples: usize) -> Self {
|
||||
ForwardPipeline {
|
||||
pipeline: None,
|
||||
bind_group: None,
|
||||
msaa_samples,
|
||||
depth_format: wgpu::TextureFormat::Depth32Float,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pipeline for ForwardPipeline {
|
||||
fn initialize(&mut self, render_graph: &mut RenderGraphData, _: &mut World) {
|
||||
let vs_bytes = shader::glsl_to_spirv(
|
||||
include_str!("forward.vert"),
|
||||
shader::ShaderStage::Vertex,
|
||||
None,
|
||||
);
|
||||
let fs_bytes = shader::glsl_to_spirv(
|
||||
include_str!("forward.frag"),
|
||||
shader::ShaderStage::Fragment,
|
||||
None,
|
||||
);
|
||||
|
||||
let bind_group_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 1, // lights
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
self.bind_group = Some({
|
||||
let forward_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::FORWARD_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
let light_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
|
||||
// Create bind group
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
bindings: &[
|
||||
wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: forward_uniform_buffer.get_binding_resource(),
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 1,
|
||||
resource: light_uniform_buffer.get_binding_resource(),
|
||||
},
|
||||
],
|
||||
})
|
||||
});
|
||||
|
||||
let material_bind_group_layout = render_graph
|
||||
.get_bind_group_layout(render_resources::MATERIAL_BIND_GROUP_LAYOUT_NAME)
|
||||
.unwrap();
|
||||
|
||||
let pipeline_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout, material_bind_group_layout],
|
||||
});
|
||||
|
||||
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
|
||||
|
||||
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
||||
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
||||
|
||||
self.pipeline = Some(render_graph.device.create_render_pipeline(
|
||||
&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vs_module,
|
||||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
||||
module: &fs_module,
|
||||
entry_point: "main",
|
||||
}),
|
||||
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
color_states: &[wgpu::ColorStateDescriptor {
|
||||
format: render_graph.swap_chain_descriptor.format,
|
||||
color_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
alpha_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
|
||||
format: self.depth_format,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::Less,
|
||||
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
}),
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
vertex_buffers: &[vertex_buffer_descriptor],
|
||||
sample_count: self.msaa_samples as u32,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
fn render(
|
||||
&mut self,
|
||||
render_graph: &RenderGraphData,
|
||||
pass: &mut wgpu::RenderPass,
|
||||
_: &SwapChainOutput,
|
||||
world: &mut World,
|
||||
) {
|
||||
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
|
||||
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let mut last_mesh_id = None;
|
||||
let mesh_query =
|
||||
<(Read<Material>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
|
||||
for (material, mesh) in mesh_query.iter(world) {
|
||||
let current_mesh_id = mesh.id;
|
||||
|
||||
let mut should_load_mesh = last_mesh_id == None;
|
||||
if let Some(last) = last_mesh_id {
|
||||
should_load_mesh = last != current_mesh_id;
|
||||
}
|
||||
|
||||
if should_load_mesh {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id_mut(mesh.id) {
|
||||
mesh_asset.setup_buffers(&render_graph.device);
|
||||
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
|
||||
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(ref mesh_asset) = mesh_storage.get_id(mesh.id) {
|
||||
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);
|
||||
pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
|
||||
};
|
||||
|
||||
last_mesh_id = Some(current_mesh_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, _: &RenderGraphData) {}
|
||||
|
||||
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
|
||||
self.pipeline.as_ref().unwrap()
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
mod forward_pass;
|
||||
mod forward_pipeline;
|
||||
|
||||
pub use forward_pass::*;
|
||||
pub use forward_pipeline::*;
|
|
@ -1,40 +0,0 @@
|
|||
#version 450
|
||||
|
||||
const int MAX_LIGHTS = 10;
|
||||
|
||||
layout(location = 0) in vec3 v_Normal;
|
||||
layout(location = 1) in vec4 v_Position;
|
||||
layout(location = 2) in vec4 v_Color;
|
||||
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
|
||||
struct Light {
|
||||
mat4 proj;
|
||||
vec4 pos;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform Globals {
|
||||
mat4 u_ViewProj;
|
||||
uvec4 u_NumLights;
|
||||
};
|
||||
layout(set = 0, binding = 1) uniform Lights {
|
||||
Light u_Lights[MAX_LIGHTS];
|
||||
};
|
||||
|
||||
void main() {
|
||||
vec3 normal = normalize(v_Normal);
|
||||
vec3 ambient = vec3(0.05, 0.05, 0.05);
|
||||
// accumulate color
|
||||
vec3 color = ambient;
|
||||
for (int i=0; i<int(u_NumLights.x) && i<MAX_LIGHTS; ++i) {
|
||||
Light light = u_Lights[i];
|
||||
// compute Lambertian diffuse term
|
||||
vec3 light_dir = normalize(light.pos.xyz - v_Position.xyz);
|
||||
float diffuse = max(0.0, dot(normal, light_dir));
|
||||
// add light contribution
|
||||
color += diffuse * light.color.xyz;
|
||||
}
|
||||
// multiply the light by material color
|
||||
o_Target = vec4(color, 1.0) * v_Color;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#version 450
|
||||
|
||||
// vertex attributes
|
||||
layout(location = 0) in vec4 a_Pos;
|
||||
layout(location = 1) in vec4 a_Normal;
|
||||
layout(location = 2) in vec2 a_Uv;
|
||||
|
||||
// Instanced attributes
|
||||
layout (location = 3) in vec3 a_instancePos;
|
||||
layout (location = 4) in vec4 a_instanceColor;
|
||||
|
||||
|
||||
layout(location = 0) out vec3 v_Normal;
|
||||
layout(location = 1) out vec4 v_Position;
|
||||
layout(location = 2) out vec4 v_Color;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Globals {
|
||||
mat4 u_ViewProj;
|
||||
uvec4 u_NumLights;
|
||||
};
|
||||
|
||||
void main() {
|
||||
v_Normal = vec3(a_Normal.xyz);
|
||||
v_Position = vec4(a_Pos) + vec4(a_instancePos, 1.0);
|
||||
v_Color = a_instanceColor;
|
||||
gl_Position = u_ViewProj * v_Position;
|
||||
}
|
|
@ -1,307 +0,0 @@
|
|||
use crate::{
|
||||
asset::*,
|
||||
prelude::LocalToWorld,
|
||||
render::{instancing::InstanceBufferInfo, *},
|
||||
};
|
||||
use legion::prelude::*;
|
||||
use std::{collections::HashMap, mem};
|
||||
use wgpu::{Device, SwapChainOutput};
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub struct ForwardInstancedPipeline {
|
||||
pub pipeline: Option<wgpu::RenderPipeline>,
|
||||
pub depth_format: wgpu::TextureFormat,
|
||||
pub local_bind_group: Option<wgpu::BindGroup>,
|
||||
pub instance_buffer_infos: Option<Vec<InstanceBufferInfo>>,
|
||||
pub msaa_samples: usize,
|
||||
}
|
||||
|
||||
impl ForwardInstancedPipeline {
|
||||
pub fn new(depth_format: wgpu::TextureFormat, msaa_samples: usize) -> Self {
|
||||
ForwardInstancedPipeline {
|
||||
pipeline: None,
|
||||
depth_format,
|
||||
msaa_samples,
|
||||
local_bind_group: None,
|
||||
instance_buffer_infos: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_instance_buffer_infos(device: &Device, world: &World) -> Vec<InstanceBufferInfo> {
|
||||
let entities = <(
|
||||
Read<Material>,
|
||||
Read<LocalToWorld>,
|
||||
Read<Handle<Mesh>>,
|
||||
Read<Instanced>,
|
||||
)>::query();
|
||||
if entities.iter(world).count() == 0 {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let uniform_size = mem::size_of::<SimpleMaterialUniforms>();
|
||||
|
||||
let mut mesh_groups: HashMap<
|
||||
usize,
|
||||
Vec<(
|
||||
legion::borrow::Ref<Material>,
|
||||
legion::borrow::Ref<LocalToWorld>,
|
||||
)>,
|
||||
> = HashMap::new();
|
||||
for (material, transform, mesh, _) in entities.iter(world) {
|
||||
match mesh_groups.get_mut(&mesh.id) {
|
||||
Some(entities) => {
|
||||
entities.push((material, transform));
|
||||
}
|
||||
None => {
|
||||
let mut entities = Vec::new();
|
||||
let id = mesh.id;
|
||||
entities.push((material, transform));
|
||||
mesh_groups.insert(id, entities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut instance_buffer_infos = Vec::new();
|
||||
for (mesh_id, mut same_mesh_entities) in mesh_groups {
|
||||
let temp_buf_data = device.create_buffer_mapped(
|
||||
same_mesh_entities.len() * uniform_size,
|
||||
wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX,
|
||||
);
|
||||
|
||||
let entity_count = same_mesh_entities.len();
|
||||
for ((material, transform), slot) in same_mesh_entities
|
||||
.drain(..)
|
||||
.zip(temp_buf_data.data.chunks_exact_mut(uniform_size))
|
||||
{
|
||||
let (_, _, translation) = transform.0.to_scale_rotation_translation();
|
||||
slot.copy_from_slice(
|
||||
SimpleMaterialUniforms {
|
||||
position: translation.into(),
|
||||
color: material.get_color().into(),
|
||||
}
|
||||
.as_bytes(),
|
||||
);
|
||||
}
|
||||
|
||||
instance_buffer_infos.push(InstanceBufferInfo {
|
||||
mesh_id,
|
||||
buffer: temp_buf_data.finish(),
|
||||
instance_count: entity_count,
|
||||
});
|
||||
}
|
||||
|
||||
instance_buffer_infos
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn create_instance_buffer_infos_direct(
|
||||
device: &Device,
|
||||
world: &World,
|
||||
) -> Vec<InstanceBufferInfo> {
|
||||
let entities = <(
|
||||
Read<Material>,
|
||||
Read<LocalToWorld>,
|
||||
Read<Handle<Mesh>>,
|
||||
Read<Instanced>,
|
||||
)>::query();
|
||||
let entities_count = entities.iter(world).count();
|
||||
|
||||
let mut last_mesh_id = None;
|
||||
let mut data = Vec::with_capacity(entities_count);
|
||||
for (material, transform, mesh, _) in entities.iter(world) {
|
||||
last_mesh_id = Some(mesh.id);
|
||||
let (_, _, translation) = transform.0.to_scale_rotation_translation();
|
||||
|
||||
data.push(SimpleMaterialUniforms {
|
||||
position: translation.into(),
|
||||
color: material.get_color().into(),
|
||||
});
|
||||
}
|
||||
|
||||
let buffer = device.create_buffer_with_data(
|
||||
data.as_bytes(),
|
||||
wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX,
|
||||
);
|
||||
|
||||
let mut instance_buffer_infos = Vec::new();
|
||||
instance_buffer_infos.push(InstanceBufferInfo {
|
||||
mesh_id: last_mesh_id.unwrap(),
|
||||
buffer,
|
||||
instance_count: entities_count,
|
||||
});
|
||||
|
||||
instance_buffer_infos
|
||||
}
|
||||
}
|
||||
|
||||
impl Pipeline for ForwardInstancedPipeline {
|
||||
fn initialize(&mut self, render_graph: &mut RenderGraphData, world: &mut World) {
|
||||
let vs_bytes = shader::glsl_to_spirv(
|
||||
include_str!("forward_instanced.vert"),
|
||||
shader::ShaderStage::Vertex,
|
||||
None,
|
||||
);
|
||||
let fs_bytes = shader::glsl_to_spirv(
|
||||
include_str!("forward_instanced.frag"),
|
||||
shader::ShaderStage::Fragment,
|
||||
None,
|
||||
);
|
||||
|
||||
let bind_group_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 1, // lights
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// TODO: this is the same as normal forward pipeline. we can probably reuse
|
||||
self.local_bind_group = Some({
|
||||
let forward_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::FORWARD_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
let light_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
|
||||
// Create bind group
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
bindings: &[
|
||||
wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: forward_uniform_buffer.get_binding_resource(),
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 1,
|
||||
resource: light_uniform_buffer.get_binding_resource(),
|
||||
},
|
||||
],
|
||||
})
|
||||
});
|
||||
|
||||
let simple_material_uniforms_size = mem::size_of::<SimpleMaterialUniforms>();
|
||||
let instance_buffer_descriptor = wgpu::VertexBufferDescriptor {
|
||||
stride: simple_material_uniforms_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Instance,
|
||||
attributes: &[
|
||||
wgpu::VertexAttributeDescriptor {
|
||||
format: wgpu::VertexFormat::Float3,
|
||||
offset: 0,
|
||||
shader_location: 3,
|
||||
},
|
||||
wgpu::VertexAttributeDescriptor {
|
||||
format: wgpu::VertexFormat::Float4,
|
||||
offset: 3 * 4,
|
||||
shader_location: 4,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
|
||||
|
||||
let pipeline_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
});
|
||||
|
||||
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
||||
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
||||
|
||||
self.pipeline = Some(render_graph.device.create_render_pipeline(
|
||||
&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vs_module,
|
||||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
||||
module: &fs_module,
|
||||
entry_point: "main",
|
||||
}),
|
||||
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
color_states: &[wgpu::ColorStateDescriptor {
|
||||
format: render_graph.swap_chain_descriptor.format,
|
||||
color_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
alpha_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
|
||||
format: self.depth_format,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::Less,
|
||||
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
}),
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
vertex_buffers: &[vertex_buffer_descriptor, instance_buffer_descriptor],
|
||||
sample_count: self.msaa_samples as u32,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
));
|
||||
|
||||
self.instance_buffer_infos = Some(Self::create_instance_buffer_infos(
|
||||
&render_graph.device,
|
||||
world,
|
||||
));
|
||||
}
|
||||
|
||||
fn render(
|
||||
&mut self,
|
||||
render_graph: &RenderGraphData,
|
||||
pass: &mut wgpu::RenderPass,
|
||||
_: &SwapChainOutput,
|
||||
world: &mut World,
|
||||
) {
|
||||
self.instance_buffer_infos = Some(Self::create_instance_buffer_infos(
|
||||
&render_graph.device,
|
||||
world,
|
||||
));
|
||||
pass.set_bind_group(0, self.local_bind_group.as_ref().unwrap(), &[]);
|
||||
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
for instance_buffer_info in self.instance_buffer_infos.as_ref().unwrap().iter() {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id_mut(instance_buffer_info.mesh_id) {
|
||||
mesh_asset.setup_buffers(&render_graph.device);
|
||||
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
|
||||
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
|
||||
pass.set_vertex_buffers(1, &[(&instance_buffer_info.buffer, 0)]);
|
||||
pass.draw_indexed(
|
||||
0..mesh_asset.indices.len() as u32,
|
||||
0,
|
||||
0..instance_buffer_info.instance_count as u32,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, _: &RenderGraphData) {}
|
||||
|
||||
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
|
||||
self.pipeline.as_ref().unwrap()
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
#version 450
|
||||
|
||||
const int MAX_LIGHTS = 10;
|
||||
|
||||
layout(location = 0) in vec3 v_Normal;
|
||||
layout(location = 1) in vec4 v_Position;
|
||||
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
|
||||
struct Light {
|
||||
mat4 proj;
|
||||
vec4 pos;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform Globals {
|
||||
mat4 u_ViewProj;
|
||||
uvec4 u_NumLights;
|
||||
};
|
||||
layout(set = 0, binding = 1) uniform Lights {
|
||||
Light u_Lights[MAX_LIGHTS];
|
||||
};
|
||||
layout(set = 0, binding = 2) uniform texture2DArray t_Shadow;
|
||||
layout(set = 0, binding = 3) uniform samplerShadow s_Shadow;
|
||||
|
||||
layout(set = 1, binding = 0) uniform Entity {
|
||||
mat4 u_World;
|
||||
vec4 u_Color;
|
||||
};
|
||||
|
||||
float fetch_shadow(int light_id, vec4 homogeneous_coords) {
|
||||
if (homogeneous_coords.w <= 0.0) {
|
||||
return 1.0;
|
||||
}
|
||||
// compute texture coordinates for shadow lookup
|
||||
vec4 light_local = vec4(
|
||||
(homogeneous_coords.xy/homogeneous_coords.w + 1.0) / 2.0,
|
||||
light_id,
|
||||
homogeneous_coords.z / homogeneous_coords.w
|
||||
);
|
||||
// do the lookup, using HW PCF and comparison
|
||||
return texture(sampler2DArrayShadow(t_Shadow, s_Shadow), light_local);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 normal = normalize(v_Normal);
|
||||
vec3 ambient = vec3(0.05, 0.05, 0.05);
|
||||
// accumulate color
|
||||
vec3 color = ambient;
|
||||
for (int i=0; i<int(u_NumLights.x) && i<MAX_LIGHTS; ++i) {
|
||||
Light light = u_Lights[i];
|
||||
// project into the light space
|
||||
float shadow = fetch_shadow(i, light.proj * v_Position);
|
||||
// compute Lambertian diffuse term
|
||||
vec3 light_dir = normalize(light.pos.xyz - v_Position.xyz);
|
||||
float diffuse = max(0.0, dot(normal, light_dir));
|
||||
// add light contribution
|
||||
color += shadow * diffuse * light.color.xyz;
|
||||
}
|
||||
// multiply the light by material color
|
||||
o_Target = vec4(color, 1.0) * u_Color;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 a_Pos;
|
||||
layout(location = 1) in vec4 a_Normal;
|
||||
layout(location = 2) in vec2 a_Uv;
|
||||
|
||||
layout(location = 0) out vec3 v_Normal;
|
||||
layout(location = 1) out vec4 v_Position;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Globals {
|
||||
mat4 u_ViewProj;
|
||||
uvec4 u_NumLights;
|
||||
};
|
||||
layout(set = 1, binding = 0) uniform Entity {
|
||||
mat4 u_World;
|
||||
vec4 u_Color;
|
||||
};
|
||||
|
||||
void main() {
|
||||
v_Normal = mat3(u_World) * vec3(a_Normal.xyz);
|
||||
v_Position = u_World * vec4(a_Pos);
|
||||
gl_Position = u_ViewProj * v_Position;
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
use crate::{
|
||||
asset::*,
|
||||
render::{passes::shadow, *},
|
||||
};
|
||||
use legion::prelude::*;
|
||||
use wgpu::SwapChainOutput;
|
||||
|
||||
pub struct ForwardShadowPassNew {
|
||||
pub pipeline: Option<wgpu::RenderPipeline>,
|
||||
pub bind_group: Option<wgpu::BindGroup>,
|
||||
pub depth_format: wgpu::TextureFormat,
|
||||
}
|
||||
|
||||
impl ForwardShadowPassNew {
|
||||
pub fn new() -> Self {
|
||||
ForwardShadowPassNew {
|
||||
pipeline: None,
|
||||
bind_group: None,
|
||||
depth_format: wgpu::TextureFormat::Depth32Float,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pipeline for ForwardShadowPassNew {
|
||||
fn initialize(&mut self, render_graph: &mut RenderGraphData, _world: &mut World) {
|
||||
let vs_bytes = shader::glsl_to_spirv(
|
||||
include_str!("forward_shadow.vert"),
|
||||
shader::ShaderStage::Vertex,
|
||||
None,
|
||||
);
|
||||
let fs_bytes = shader::glsl_to_spirv(
|
||||
include_str!("forward_shadow.frag"),
|
||||
shader::ShaderStage::Fragment,
|
||||
None,
|
||||
);
|
||||
|
||||
let bind_group_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 1, // lights
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
multisampled: false,
|
||||
dimension: wgpu::TextureViewDimension::D2Array,
|
||||
},
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 3,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
self.bind_group = Some({
|
||||
let forward_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::FORWARD_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
let light_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
let shadow_sampler = render_graph
|
||||
.get_sampler(shadow::SHADOW_SAMPLER_NAME)
|
||||
.unwrap();
|
||||
let shadow_texture = render_graph
|
||||
.get_texture(shadow::SHADOW_TEXTURE_NAME)
|
||||
.unwrap();
|
||||
|
||||
// Create bind group
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
bindings: &[
|
||||
wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: forward_uniform_buffer.get_binding_resource(),
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 1,
|
||||
resource: light_uniform_buffer.get_binding_resource(),
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::TextureView(shadow_texture),
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 3,
|
||||
resource: wgpu::BindingResource::Sampler(shadow_sampler),
|
||||
},
|
||||
],
|
||||
})
|
||||
});
|
||||
|
||||
let material_bind_group_layout = render_graph
|
||||
.get_bind_group_layout(render_resources::MATERIAL_BIND_GROUP_LAYOUT_NAME)
|
||||
.unwrap();
|
||||
|
||||
let pipeline_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout, material_bind_group_layout],
|
||||
});
|
||||
|
||||
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
||||
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
||||
|
||||
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
|
||||
|
||||
self.pipeline = Some(render_graph.device.create_render_pipeline(
|
||||
&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vs_module,
|
||||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
||||
module: &fs_module,
|
||||
entry_point: "main",
|
||||
}),
|
||||
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
color_states: &[wgpu::ColorStateDescriptor {
|
||||
format: render_graph.swap_chain_descriptor.format,
|
||||
color_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
alpha_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
|
||||
format: self.depth_format,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::Less,
|
||||
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
}),
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
vertex_buffers: &[vertex_buffer_descriptor],
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
fn render(
|
||||
&mut self,
|
||||
render_graph: &RenderGraphData,
|
||||
pass: &mut wgpu::RenderPass,
|
||||
_swap_chain_output: &SwapChainOutput,
|
||||
world: &mut World,
|
||||
) {
|
||||
let mesh_query = <(Read<Material>, Read<Handle<Mesh>>)>::query();
|
||||
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
|
||||
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
for (material, mesh) in mesh_query.iter(world) {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id_mut(mesh.id) {
|
||||
mesh_asset.setup_buffers(&render_graph.device);
|
||||
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);
|
||||
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
|
||||
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
|
||||
pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, _render_graph: &RenderGraphData) {}
|
||||
|
||||
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
|
||||
self.pipeline.as_ref().unwrap()
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
mod forward;
|
||||
mod forward_instanced;
|
||||
mod forward_shadow;
|
||||
mod shadow;
|
||||
mod ui;
|
||||
|
||||
pub use forward::{ForwardPass, ForwardPipeline, ForwardUniforms};
|
||||
pub use forward_instanced::ForwardInstancedPipeline;
|
||||
pub use forward_shadow::ForwardShadowPassNew;
|
||||
pub use shadow::ShadowPass;
|
||||
pub use ui::UiPipeline;
|
|
@ -1,5 +0,0 @@
|
|||
mod shadow_pass;
|
||||
mod shadow_pipeline;
|
||||
|
||||
pub use shadow_pass::*;
|
||||
pub use shadow_pipeline::*;
|
|
@ -1,4 +0,0 @@
|
|||
#version 450
|
||||
|
||||
void main() {
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 a_Pos;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Globals {
|
||||
mat4 u_ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0) uniform Entity {
|
||||
mat4 u_World;
|
||||
vec4 u_Color;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = u_ViewProj * u_World * vec4(a_Pos);
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
use crate::{
|
||||
prelude::{LocalToWorld, Translation},
|
||||
render::{passes::shadow, *},
|
||||
};
|
||||
use legion::prelude::*;
|
||||
use std::mem;
|
||||
|
||||
pub struct ShadowPass {
|
||||
pub shadow_size: wgpu::Extent3d,
|
||||
light_index: isize,
|
||||
shadow_texture: Option<wgpu::Texture>,
|
||||
shadow_format: wgpu::TextureFormat,
|
||||
pub max_lights: usize,
|
||||
}
|
||||
|
||||
pub const SHADOW_TEXTURE_NAME: &str = "shadow_texture";
|
||||
|
||||
impl ShadowPass {
|
||||
pub fn new(
|
||||
shadow_size: wgpu::Extent3d,
|
||||
shadow_format: wgpu::TextureFormat,
|
||||
max_lights: usize,
|
||||
) -> Self {
|
||||
ShadowPass {
|
||||
light_index: -1,
|
||||
shadow_texture: None,
|
||||
shadow_size,
|
||||
shadow_format,
|
||||
max_lights,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pass for ShadowPass {
|
||||
fn initialize(&self, render_graph: &mut RenderGraphData) {
|
||||
let shadow_texture = render_graph
|
||||
.device
|
||||
.create_texture(&wgpu::TextureDescriptor {
|
||||
size: self.shadow_size,
|
||||
array_layer_count: self.max_lights as u32,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: self.shadow_format,
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
|
||||
});
|
||||
|
||||
let shadow_view = shadow_texture.create_default_view();
|
||||
render_graph.set_texture(SHADOW_TEXTURE_NAME, shadow_view);
|
||||
}
|
||||
|
||||
fn begin<'a>(
|
||||
&mut self,
|
||||
render_graph: &mut RenderGraphData,
|
||||
world: &mut World,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
_frame: &'a wgpu::SwapChainOutput,
|
||||
) -> Option<wgpu::RenderPass<'a>> {
|
||||
if self.light_index == -1 {
|
||||
self.light_index = 0;
|
||||
}
|
||||
|
||||
let light_query = <(Write<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
|
||||
let light_count = light_query.iter_mut(world).count();
|
||||
for (i, (mut light, _, _)) in light_query.iter_mut(world).enumerate() {
|
||||
if i != self.light_index as usize {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let None = light.target_view {
|
||||
light.target_view = Some(self.shadow_texture.as_ref().unwrap().create_view(
|
||||
&wgpu::TextureViewDescriptor {
|
||||
format: self.shadow_format,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
base_mip_level: 0,
|
||||
level_count: 1,
|
||||
base_array_layer: i as u32,
|
||||
array_layer_count: 1,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
// The light uniform buffer already has the projection,
|
||||
// let's just copy it over to the shadow uniform buffer.
|
||||
let light_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
let shadow_pipeline_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(shadow::SHADOW_PIPELINE_UNIFORMS)
|
||||
.unwrap();
|
||||
encoder.copy_buffer_to_buffer(
|
||||
&light_uniform_buffer.buffer,
|
||||
(i * mem::size_of::<LightRaw>()) as wgpu::BufferAddress,
|
||||
&shadow_pipeline_uniform_buffer.buffer,
|
||||
0,
|
||||
64,
|
||||
);
|
||||
|
||||
self.light_index += 1;
|
||||
if self.light_index as usize == light_count {
|
||||
self.light_index = -1;
|
||||
}
|
||||
return Some(encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[],
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: light.target_view.as_ref().unwrap(),
|
||||
depth_load_op: wgpu::LoadOp::Clear,
|
||||
depth_store_op: wgpu::StoreOp::Store,
|
||||
stencil_load_op: wgpu::LoadOp::Clear,
|
||||
stencil_store_op: wgpu::StoreOp::Store,
|
||||
clear_depth: 1.0,
|
||||
clear_stencil: 0,
|
||||
}),
|
||||
}));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn resize(&self, _render_graph: &mut RenderGraphData) {}
|
||||
|
||||
fn should_repeat(&self) -> bool {
|
||||
return self.light_index != -1;
|
||||
}
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
use crate::{asset::*, render::*};
|
||||
use legion::prelude::*;
|
||||
use std::mem;
|
||||
use wgpu::SwapChainOutput;
|
||||
|
||||
pub const SHADOW_PIPELINE_UNIFORMS: &str = "shadow_pipeline";
|
||||
pub const SHADOW_SAMPLER_NAME: &str = "shadow_sampler";
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ShadowUniforms {
|
||||
pub proj: [[f32; 4]; 4],
|
||||
}
|
||||
|
||||
pub struct ShadowPipeline {
|
||||
pub pipeline: Option<wgpu::RenderPipeline>,
|
||||
pub bind_group: Option<wgpu::BindGroup>,
|
||||
pub shadow_format: wgpu::TextureFormat,
|
||||
}
|
||||
|
||||
impl ShadowPipeline {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(shadow_format: wgpu::TextureFormat) -> Self {
|
||||
ShadowPipeline {
|
||||
bind_group: None,
|
||||
pipeline: None,
|
||||
shadow_format,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pipeline for ShadowPipeline {
|
||||
fn initialize(&mut self, render_graph: &mut RenderGraphData, _: &mut World) {
|
||||
let bind_group_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[wgpu::BindGroupLayoutBinding {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
}],
|
||||
});
|
||||
|
||||
let material_bind_group_layout = render_graph
|
||||
.get_bind_group_layout(render_resources::MATERIAL_BIND_GROUP_LAYOUT_NAME)
|
||||
.unwrap();
|
||||
|
||||
let pipeline_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout, material_bind_group_layout],
|
||||
});
|
||||
|
||||
let uniform_size = mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress;
|
||||
let uniform_buf = render_graph.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size: uniform_size,
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
});
|
||||
|
||||
// Create bind group
|
||||
self.bind_group = Some(
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
bindings: &[wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer {
|
||||
buffer: &uniform_buf,
|
||||
range: 0..uniform_size,
|
||||
},
|
||||
}],
|
||||
}),
|
||||
);
|
||||
|
||||
render_graph.set_uniform_buffer(
|
||||
SHADOW_PIPELINE_UNIFORMS,
|
||||
UniformBuffer {
|
||||
buffer: uniform_buf,
|
||||
size: uniform_size,
|
||||
},
|
||||
);
|
||||
|
||||
// Create other resources
|
||||
let shadow_sampler = render_graph
|
||||
.device
|
||||
.create_sampler(&wgpu::SamplerDescriptor {
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
lod_min_clamp: -100.0,
|
||||
lod_max_clamp: 100.0,
|
||||
compare_function: wgpu::CompareFunction::LessEqual,
|
||||
});
|
||||
|
||||
render_graph.set_sampler(SHADOW_SAMPLER_NAME, shadow_sampler);
|
||||
|
||||
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
|
||||
|
||||
// Create the render pipeline
|
||||
let vs_bytes = shader::glsl_to_spirv(
|
||||
include_str!("shadow.vert"),
|
||||
shader::ShaderStage::Vertex,
|
||||
None,
|
||||
);
|
||||
let fs_bytes = shader::glsl_to_spirv(
|
||||
include_str!("shadow.frag"),
|
||||
shader::ShaderStage::Fragment,
|
||||
None,
|
||||
);
|
||||
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
||||
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
||||
|
||||
self.pipeline = Some(render_graph.device.create_render_pipeline(
|
||||
&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vs_module,
|
||||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
||||
module: &fs_module,
|
||||
entry_point: "main",
|
||||
}),
|
||||
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
depth_bias: 2, // corresponds to bilinear filtering
|
||||
depth_bias_slope_scale: 2.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
color_states: &[],
|
||||
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
|
||||
format: self.shadow_format,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::LessEqual,
|
||||
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
}),
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
vertex_buffers: &[vertex_buffer_descriptor],
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
fn render(
|
||||
&mut self,
|
||||
render_graph: &RenderGraphData,
|
||||
pass: &mut wgpu::RenderPass,
|
||||
_: &SwapChainOutput,
|
||||
world: &mut World,
|
||||
) {
|
||||
let mesh_query =
|
||||
<(Read<Material>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
|
||||
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
|
||||
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
for (material, mesh) in mesh_query.iter(world) {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id_mut(mesh.id) {
|
||||
mesh_asset.setup_buffers(&render_graph.device);
|
||||
|
||||
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);
|
||||
pass.set_index_buffer(&mesh_asset.index_buffer.as_ref().unwrap(), 0);
|
||||
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
|
||||
pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, _: &RenderGraphData) {}
|
||||
|
||||
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
|
||||
self.pipeline.as_ref().unwrap()
|
||||
}
|
||||
}
|
|
@ -1,264 +0,0 @@
|
|||
use crate::{
|
||||
asset::*,
|
||||
ecs, math,
|
||||
prelude::Parent,
|
||||
render::{instancing::InstanceBufferInfo, *},
|
||||
ui::Node,
|
||||
};
|
||||
use legion::prelude::*;
|
||||
use wgpu::SwapChainOutput;
|
||||
use zerocopy::{AsBytes, FromBytes};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
pub struct RectData {
|
||||
pub position: [f32; 2],
|
||||
pub size: [f32; 2],
|
||||
pub color: [f32; 4],
|
||||
pub z_index: f32,
|
||||
}
|
||||
|
||||
pub struct UiPipeline {
|
||||
pub pipeline: Option<wgpu::RenderPipeline>,
|
||||
pub depth_format: wgpu::TextureFormat,
|
||||
pub quad: Option<Handle<Mesh>>,
|
||||
pub bind_group: Option<wgpu::BindGroup>,
|
||||
pub msaa_samples: usize,
|
||||
}
|
||||
|
||||
impl UiPipeline {
|
||||
pub fn new(msaa_samples: usize) -> Self {
|
||||
UiPipeline {
|
||||
pipeline: None,
|
||||
bind_group: None,
|
||||
msaa_samples,
|
||||
quad: None,
|
||||
depth_format: wgpu::TextureFormat::Depth32Float,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_rect_buffers(
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
world: &mut World,
|
||||
) -> Vec<InstanceBufferInfo> {
|
||||
let node_query = <Read<Node>>::query().filter(!component::<Parent>());
|
||||
|
||||
if node_query.iter(world).count() == 0 {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut data = Vec::new();
|
||||
// TODO: this probably isn't the best way to handle z-ordering
|
||||
let mut z = 0.9999;
|
||||
{
|
||||
let mut add_data: Box<dyn FnMut(&World, Entity, ()) -> Option<()>> =
|
||||
Box::new(|world, entity, _| {
|
||||
let node = world.get_component::<Node>(entity).unwrap();
|
||||
data.push(RectData {
|
||||
position: node.global_position.into(),
|
||||
size: node.size.into(),
|
||||
color: node.color.into(),
|
||||
z_index: z,
|
||||
});
|
||||
|
||||
z -= 0.0001;
|
||||
Some(())
|
||||
});
|
||||
|
||||
for entity in node_query
|
||||
.iter_entities(world)
|
||||
.map(|(entity, _)| entity)
|
||||
.collect::<Vec<Entity>>()
|
||||
{
|
||||
ecs::run_on_hierarchy(world, entity, (), &mut add_data);
|
||||
}
|
||||
}
|
||||
|
||||
let buffer = device.create_buffer_with_data(
|
||||
data.as_bytes(),
|
||||
wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX,
|
||||
);
|
||||
|
||||
let mesh_id = self.quad.as_ref().unwrap().id;
|
||||
|
||||
let mut instance_buffer_infos = Vec::new();
|
||||
instance_buffer_infos.push(InstanceBufferInfo {
|
||||
mesh_id,
|
||||
buffer,
|
||||
instance_count: data.len(),
|
||||
});
|
||||
|
||||
instance_buffer_infos
|
||||
}
|
||||
}
|
||||
|
||||
impl Pipeline for UiPipeline {
|
||||
fn initialize(&mut self, render_graph: &mut RenderGraphData, world: &mut World) {
|
||||
let vs_bytes =
|
||||
shader::glsl_to_spirv(include_str!("ui.vert"), shader::ShaderStage::Vertex, None);
|
||||
let fs_bytes =
|
||||
shader::glsl_to_spirv(include_str!("ui.frag"), shader::ShaderStage::Fragment, None);
|
||||
|
||||
let bind_group_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[wgpu::BindGroupLayoutBinding {
|
||||
binding: 0, // global_2d
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
}],
|
||||
});
|
||||
|
||||
self.bind_group = Some({
|
||||
let global_2d_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::GLOBAL_2D_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
|
||||
// Create bind group
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
bindings: &[wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: global_2d_uniform_buffer.get_binding_resource(),
|
||||
}],
|
||||
})
|
||||
});
|
||||
|
||||
{
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
|
||||
let quad = Mesh::load(MeshType::Quad {
|
||||
north_west: math::vec2(-0.5, 0.5),
|
||||
north_east: math::vec2(0.5, 0.5),
|
||||
south_west: math::vec2(-0.5, -0.5),
|
||||
south_east: math::vec2(0.5, -0.5),
|
||||
});
|
||||
self.quad = Some(mesh_storage.add(quad));
|
||||
}
|
||||
|
||||
let pipeline_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
});
|
||||
|
||||
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
|
||||
let rect_data_size = mem::size_of::<RectData>();
|
||||
let instance_buffer_descriptor = wgpu::VertexBufferDescriptor {
|
||||
stride: rect_data_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Instance,
|
||||
attributes: &[
|
||||
wgpu::VertexAttributeDescriptor {
|
||||
format: wgpu::VertexFormat::Float2,
|
||||
offset: 0,
|
||||
shader_location: 3,
|
||||
},
|
||||
wgpu::VertexAttributeDescriptor {
|
||||
format: wgpu::VertexFormat::Float2,
|
||||
offset: 2 * 4,
|
||||
shader_location: 4,
|
||||
},
|
||||
wgpu::VertexAttributeDescriptor {
|
||||
format: wgpu::VertexFormat::Float4,
|
||||
offset: 4 * 4,
|
||||
shader_location: 5,
|
||||
},
|
||||
wgpu::VertexAttributeDescriptor {
|
||||
format: wgpu::VertexFormat::Float,
|
||||
offset: 8 * 4,
|
||||
shader_location: 6,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
||||
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
||||
|
||||
let pipedesc = wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vs_module,
|
||||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
||||
module: &fs_module,
|
||||
entry_point: "main",
|
||||
}),
|
||||
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::None,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
color_states: &[wgpu::ColorStateDescriptor {
|
||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: wgpu::BlendDescriptor {
|
||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||
operation: wgpu::BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: wgpu::BlendDescriptor {
|
||||
src_factor: wgpu::BlendFactor::One,
|
||||
dst_factor: wgpu::BlendFactor::One,
|
||||
operation: wgpu::BlendOperation::Add,
|
||||
},
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
|
||||
format: self.depth_format,
|
||||
depth_write_enabled: false,
|
||||
depth_compare: wgpu::CompareFunction::Always,
|
||||
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
}),
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
vertex_buffers: &[vertex_buffer_descriptor, instance_buffer_descriptor],
|
||||
sample_count: self.msaa_samples as u32,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
};
|
||||
|
||||
self.pipeline = Some(render_graph.device.create_render_pipeline(&pipedesc));
|
||||
}
|
||||
|
||||
fn render(
|
||||
&mut self,
|
||||
render_graph: &RenderGraphData,
|
||||
pass: &mut wgpu::RenderPass,
|
||||
_: &SwapChainOutput,
|
||||
world: &mut World,
|
||||
) {
|
||||
let instance_buffer_infos = Some(self.create_rect_buffers(&render_graph.device, world));
|
||||
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
|
||||
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
for instance_buffer_info in instance_buffer_infos.as_ref().unwrap().iter() {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id_mut(instance_buffer_info.mesh_id) {
|
||||
mesh_asset.setup_buffers(&render_graph.device);
|
||||
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
|
||||
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
|
||||
pass.set_vertex_buffers(1, &[(&instance_buffer_info.buffer, 0)]);
|
||||
pass.draw_indexed(
|
||||
0..mesh_asset.indices.len() as u32,
|
||||
0,
|
||||
0..instance_buffer_info.instance_count as u32,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, _: &RenderGraphData) {}
|
||||
|
||||
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
|
||||
self.pipeline.as_ref().unwrap()
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
#version 450
|
||||
|
||||
// vertex attributes
|
||||
layout(location = 0) in vec4 a_Pos;
|
||||
layout(location = 1) in vec4 a_Normal;
|
||||
layout(location = 2) in vec2 a_Uv;
|
||||
|
||||
// instanced attributes (RectData)
|
||||
layout (location = 3) in vec2 a_RectPosition;
|
||||
layout (location = 4) in vec2 a_RectSize;
|
||||
layout (location = 5) in vec4 a_RectColor;
|
||||
layout (location = 6) in float a_RectZIndex;
|
||||
|
||||
layout(location = 0) out vec4 v_Color;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Globals {
|
||||
mat4 u_ViewProj;
|
||||
};
|
||||
|
||||
void main() {
|
||||
v_Color = a_RectColor;
|
||||
vec4 position = a_Pos * vec4(a_RectSize, 0.0, 1.0);
|
||||
position = position + vec4(a_RectPosition + a_RectSize / 2.0, -a_RectZIndex, 0.0);
|
||||
gl_Position = u_ViewProj * position;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{asset::Handle, render::render_graph_2::{pipeline::PipelineDescriptor, RenderPass}};
|
||||
use crate::{asset::Handle, render::render_graph::{pipeline::PipelineDescriptor, RenderPass}};
|
||||
use legion::prelude::World;
|
||||
|
||||
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
asset::{AssetStorage, Handle, Mesh},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
render_graph_2::{resource_name, RenderPass, Renderable, PipelineDescriptor, ShaderPipelineAssignments},
|
||||
render_graph::{resource_name, RenderPass, Renderable, PipelineDescriptor, ShaderPipelineAssignments},
|
||||
},
|
||||
};
|
||||
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
asset::{AssetStorage, Handle, Mesh},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
render_graph_2::{resource_name, RenderPass, Renderable, ShaderUniforms, PipelineDescriptor},
|
||||
render_graph::{resource_name, RenderPass, Renderable, ShaderUniforms, PipelineDescriptor},
|
||||
Instanced,
|
||||
},
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Mesh, Handle},
|
||||
legion::prelude::*,
|
||||
render::render_graph_2::{resource_name, RenderPass, ResourceInfo, PipelineDescriptor},
|
||||
render::render_graph::{resource_name, RenderPass, ResourceInfo, PipelineDescriptor},
|
||||
};
|
||||
|
||||
use zerocopy::AsBytes;
|
|
@ -1,11 +1,29 @@
|
|||
mod draw_target;
|
||||
pub mod draw_targets;
|
||||
mod pass;
|
||||
pub mod passes;
|
||||
mod pipeline;
|
||||
mod pipeline_layout;
|
||||
pub mod pipelines;
|
||||
mod render_graph;
|
||||
mod render_graph_data;
|
||||
mod render_resource_manager;
|
||||
mod renderable;
|
||||
mod renderer;
|
||||
pub mod renderers;
|
||||
mod resource;
|
||||
pub mod resource_name;
|
||||
pub mod resource_provider;
|
||||
pub mod resource_providers;
|
||||
mod uniform;
|
||||
mod uniforms;
|
||||
|
||||
pub use pass::Pass;
|
||||
pub use pipeline::Pipeline;
|
||||
pub use draw_target::*;
|
||||
pub use pass::*;
|
||||
pub use pipeline::*;
|
||||
pub use pipeline_layout::*;
|
||||
pub use render_graph::*;
|
||||
pub use render_graph_data::*;
|
||||
pub use render_resource_manager::RenderResourceManager;
|
||||
pub use renderable::*;
|
||||
pub use renderer::*;
|
||||
pub use resource::*;
|
||||
pub use resource_provider::*;
|
||||
pub use uniform::*;
|
||||
pub use uniforms::*;
|
||||
|
|
|
@ -1,15 +1,33 @@
|
|||
use crate::render::render_graph::RenderGraphData;
|
||||
use legion::world::World;
|
||||
pub struct RenderPassColorAttachmentDescriptor {
|
||||
/// The actual color attachment.
|
||||
pub attachment: String,
|
||||
|
||||
pub trait Pass {
|
||||
fn initialize(&self, render_graph: &mut RenderGraphData);
|
||||
fn begin<'a>(
|
||||
&mut self,
|
||||
render_graph: &mut RenderGraphData,
|
||||
world: &mut World,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
frame: &'a wgpu::SwapChainOutput,
|
||||
) -> Option<wgpu::RenderPass<'a>>;
|
||||
fn should_repeat(&self) -> bool;
|
||||
fn resize(&self, render_graph: &mut RenderGraphData);
|
||||
/// The resolve target for this color attachment, if any.
|
||||
pub resolve_target: Option<String>,
|
||||
|
||||
/// The beginning-of-pass load operation for this color attachment.
|
||||
pub load_op: wgpu::LoadOp,
|
||||
|
||||
/// The end-of-pass store operation for this color attachment.
|
||||
pub store_op: wgpu::StoreOp,
|
||||
|
||||
/// The color that will be assigned to every pixel of this attachment when cleared.
|
||||
pub clear_color: wgpu::Color,
|
||||
}
|
||||
|
||||
pub struct RenderPassDepthStencilAttachmentDescriptor {
|
||||
pub attachment: String,
|
||||
pub depth_load_op: wgpu::LoadOp,
|
||||
pub depth_store_op: wgpu::StoreOp,
|
||||
pub clear_depth: f32,
|
||||
pub stencil_load_op: wgpu::LoadOp,
|
||||
pub stencil_store_op: wgpu::StoreOp,
|
||||
pub clear_stencil: u32,
|
||||
}
|
||||
|
||||
// A set of pipeline bindings and draw calls with color and depth outputs
|
||||
pub struct PassDescriptor {
|
||||
pub color_attachments: Vec<RenderPassColorAttachmentDescriptor>,
|
||||
pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachmentDescriptor>,
|
||||
pub sample_count: u32,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::render::render_graph_2::{
|
||||
use crate::render::render_graph::{
|
||||
resource_name, resource_providers::FrameTextureResourceProvider, PassDescriptor,
|
||||
RenderGraphBuilder, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, TextureDescriptor, TextureDimension,
|
|
@ -1,16 +1,209 @@
|
|||
use crate::render::RenderGraphData;
|
||||
use legion::world::World;
|
||||
use wgpu::SwapChainOutput;
|
||||
use crate::{asset::{AssetStorage, Handle}, render::{
|
||||
render_graph::{BindGroup, PipelineLayout},
|
||||
shader::{Shader, ShaderStages},
|
||||
}};
|
||||
|
||||
pub trait Pipeline {
|
||||
fn initialize(&mut self, render_graph: &mut RenderGraphData, world: &mut World);
|
||||
fn render(
|
||||
&mut self,
|
||||
render_graph: &RenderGraphData,
|
||||
pass: &mut wgpu::RenderPass,
|
||||
frame: &SwapChainOutput,
|
||||
world: &mut World,
|
||||
);
|
||||
fn resize(&mut self, render_graph: &RenderGraphData);
|
||||
fn get_pipeline(&self) -> &wgpu::RenderPipeline;
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VertexBufferDescriptor {
|
||||
pub stride: wgpu::BufferAddress,
|
||||
pub step_mode: wgpu::InputStepMode,
|
||||
pub attributes: Vec<wgpu::VertexAttributeDescriptor>,
|
||||
}
|
||||
|
||||
impl<'a> Into<wgpu::VertexBufferDescriptor<'a>> for &'a VertexBufferDescriptor {
|
||||
fn into(self) -> wgpu::VertexBufferDescriptor<'a> {
|
||||
wgpu::VertexBufferDescriptor {
|
||||
step_mode: self.step_mode,
|
||||
stride: self.stride,
|
||||
attributes: &self.attributes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PipelineLayoutType {
|
||||
Manual(PipelineLayout),
|
||||
Reflected(Option<PipelineLayout>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PipelineDescriptor {
|
||||
pub draw_targets: Vec<String>,
|
||||
pub layout: PipelineLayoutType,
|
||||
pub shader_stages: ShaderStages,
|
||||
pub rasterization_state: Option<wgpu::RasterizationStateDescriptor>,
|
||||
|
||||
/// The primitive topology used to interpret vertices.
|
||||
pub primitive_topology: wgpu::PrimitiveTopology,
|
||||
|
||||
/// The effect of draw calls on the color aspect of the output target.
|
||||
pub color_states: Vec<wgpu::ColorStateDescriptor>,
|
||||
|
||||
/// The effect of draw calls on the depth and stencil aspects of the output target, if any.
|
||||
pub depth_stencil_state: Option<wgpu::DepthStencilStateDescriptor>,
|
||||
|
||||
/// The format of any index buffers used with this pipeline.
|
||||
pub index_format: wgpu::IndexFormat,
|
||||
|
||||
/// The format of any vertex buffers used with this pipeline.
|
||||
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>,
|
||||
|
||||
/// The number of samples calculated per pixel (for MSAA).
|
||||
pub sample_count: u32,
|
||||
|
||||
/// Bitmask that restricts the samples of a pixel modified by this pipeline.
|
||||
pub sample_mask: u32,
|
||||
|
||||
/// When enabled, produces another sample mask per pixel based on the alpha output value, that
|
||||
/// is ANDed with the sample_mask and the primitive coverage to restrict the set of samples
|
||||
/// affected by a primitive.
|
||||
/// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
|
||||
/// is guaranteed to be all 1-s.
|
||||
pub alpha_to_coverage_enabled: bool,
|
||||
}
|
||||
|
||||
impl PipelineDescriptor {
|
||||
fn new(vertex_shader: Handle<Shader>) -> Self {
|
||||
PipelineDescriptor {
|
||||
layout: PipelineLayoutType::Reflected(None),
|
||||
color_states: Vec::new(),
|
||||
depth_stencil_state: None,
|
||||
draw_targets: Vec::new(),
|
||||
shader_stages: ShaderStages::new(vertex_shader),
|
||||
vertex_buffer_descriptors: Vec::new(),
|
||||
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_layout(&self) -> Option<&PipelineLayout> {
|
||||
match self.layout {
|
||||
PipelineLayoutType::Reflected(ref layout) => layout.as_ref(),
|
||||
PipelineLayoutType::Manual(ref layout) => Some(layout),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_layout_mut(&mut self) -> Option<&mut PipelineLayout> {
|
||||
match self.layout {
|
||||
PipelineLayoutType::Reflected(ref mut layout) => layout.as_mut(),
|
||||
PipelineLayoutType::Manual(ref mut layout) => Some(layout),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PipelineDescriptor {
|
||||
pub fn build(shader_storage: &mut AssetStorage<Shader>, vertex_shader: Shader) -> PipelineBuilder {
|
||||
PipelineBuilder::new(shader_storage, vertex_shader)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PipelineBuilder<'a> {
|
||||
pipeline: PipelineDescriptor,
|
||||
shader_storage: &'a mut AssetStorage<Shader>,
|
||||
}
|
||||
|
||||
impl<'a> PipelineBuilder<'a> {
|
||||
pub fn new(shader_storage: &'a mut AssetStorage<Shader>, vertex_shader: Shader) -> Self {
|
||||
let vertex_shader_handle = shader_storage.add(vertex_shader);
|
||||
PipelineBuilder {
|
||||
pipeline: PipelineDescriptor::new(vertex_shader_handle),
|
||||
shader_storage,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(self) -> PipelineDescriptor {
|
||||
self.pipeline
|
||||
}
|
||||
|
||||
pub fn with_fragment_shader(mut self, fragment_shader: Shader) -> Self {
|
||||
let fragment_shader_handle = self.shader_storage.add(fragment_shader);
|
||||
self.pipeline.shader_stages.fragment = Some(fragment_shader_handle);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_color_state(mut self, color_state_descriptor: wgpu::ColorStateDescriptor) -> Self {
|
||||
self.pipeline.color_states.push(color_state_descriptor);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_depth_stencil_state(
|
||||
mut self,
|
||||
depth_stencil_state: wgpu::DepthStencilStateDescriptor,
|
||||
) -> Self {
|
||||
if let Some(_) = self.pipeline.depth_stencil_state {
|
||||
panic!("Depth stencil state has already been set");
|
||||
}
|
||||
self.pipeline.depth_stencil_state = Some(depth_stencil_state);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_bind_group(mut self, bind_group: BindGroup) -> Self {
|
||||
if let PipelineLayoutType::Reflected(_) = self.pipeline.layout {
|
||||
self.pipeline.layout = PipelineLayoutType::Manual(PipelineLayout::new());
|
||||
}
|
||||
|
||||
if let PipelineLayoutType::Manual(ref mut layout) = self.pipeline.layout {
|
||||
layout.bind_groups.push(bind_group);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_vertex_buffer_descriptor(
|
||||
mut self,
|
||||
vertex_buffer_descriptor: VertexBufferDescriptor,
|
||||
) -> Self {
|
||||
self.pipeline
|
||||
.vertex_buffer_descriptors
|
||||
.push(vertex_buffer_descriptor);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_index_format(mut self, index_format: wgpu::IndexFormat) -> Self {
|
||||
self.pipeline.index_format = index_format;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_draw_target(mut self, name: &str) -> Self {
|
||||
self.pipeline.draw_targets.push(name.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_rasterization_state(
|
||||
mut self,
|
||||
rasterization_state: wgpu::RasterizationStateDescriptor,
|
||||
) -> Self {
|
||||
self.pipeline.rasterization_state = Some(rasterization_state);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_primitive_topology(mut self, primitive_topology: wgpu::PrimitiveTopology) -> Self {
|
||||
self.pipeline.primitive_topology = primitive_topology;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_sample_count(mut self, sample_count: u32) -> Self {
|
||||
self.pipeline.sample_count = sample_count;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_alpha_to_coverage_enabled(mut self, alpha_to_coverage_enabled: bool) -> Self {
|
||||
self.pipeline.alpha_to_coverage_enabled = alpha_to_coverage_enabled;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_sample_mask(mut self, sample_mask: u32) -> Self {
|
||||
self.pipeline.sample_mask = sample_mask;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
asset::AssetStorage,
|
||||
render::{
|
||||
render_graph_2::{resource_name, PipelineDescriptor, RenderGraphBuilder},
|
||||
render_graph::{resource_name, PipelineDescriptor, RenderGraphBuilder},
|
||||
shader::{Shader, ShaderStage},
|
||||
Vertex,
|
||||
},
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{
|
||||
asset::AssetStorage,
|
||||
render::{
|
||||
render_graph_2::{
|
||||
resource_name, pipeline_layout::*, PipelineDescriptor,
|
||||
render_graph::{
|
||||
resource_name, PipelineDescriptor,
|
||||
RenderGraphBuilder,
|
||||
},
|
||||
shader::{Shader, ShaderStage},
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{
|
||||
asset::AssetStorage,
|
||||
render::{
|
||||
render_graph_2::{
|
||||
pipeline_layout::*, resource_providers::RectData,
|
||||
render_graph::{
|
||||
resource_providers::RectData,
|
||||
PipelineDescriptor, RenderGraphBuilder, VertexBufferDescriptor, resource_name,
|
||||
},
|
||||
shader::{Shader, ShaderStage},
|
|
@ -1,182 +1,115 @@
|
|||
use crate::render::{Pass, Pipeline, RenderGraphData, RenderResourceManager};
|
||||
use legion::world::World;
|
||||
use std::{collections::HashMap, ops::Deref};
|
||||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
render::render_graph::{
|
||||
DrawTarget, PassDescriptor, PipelineDescriptor, ResourceProvider, TextureDescriptor,
|
||||
},
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub struct RenderGraph {
|
||||
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>>,
|
||||
swap_chain: Option<wgpu::SwapChain>,
|
||||
pub pipeline_descriptors: HashSet<Handle<PipelineDescriptor>>,
|
||||
// TODO: make this ordered
|
||||
pub pass_descriptors: HashMap<String, PassDescriptor>,
|
||||
pub pass_pipelines: HashMap<String, Vec<Handle<PipelineDescriptor>>>,
|
||||
pub resource_providers: Vec<Box<dyn ResourceProvider>>,
|
||||
pub queued_textures: Vec<(String, TextureDescriptor)>,
|
||||
pub draw_targets: HashMap<String, DrawTarget>,
|
||||
}
|
||||
|
||||
impl Default for RenderGraph {
|
||||
fn default() -> Self {
|
||||
RenderGraph {
|
||||
pipeline_descriptors: HashSet::new(),
|
||||
pass_descriptors: HashMap::new(),
|
||||
pass_pipelines: HashMap::new(),
|
||||
resource_providers: Vec::new(),
|
||||
queued_textures: Vec::new(),
|
||||
draw_targets: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderGraph {
|
||||
pub fn new() -> Self {
|
||||
RenderGraph {
|
||||
passes: HashMap::new(),
|
||||
pipelines: HashMap::new(),
|
||||
pass_pipelines: HashMap::new(),
|
||||
render_resource_managers: Vec::new(),
|
||||
data: None,
|
||||
swap_chain: None,
|
||||
}
|
||||
}
|
||||
pub fn add_pipeline(&mut self, pass: &str, pipeline: Handle<PipelineDescriptor>) {
|
||||
self.pipeline_descriptors.insert(pipeline.clone());
|
||||
|
||||
pub fn initialize(&mut self, world: &mut World) {
|
||||
let adapter = wgpu::Adapter::request(
|
||||
&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
limits: wgpu::Limits::default(),
|
||||
});
|
||||
|
||||
let (surface, window_size) = {
|
||||
let window = world.resources.get::<winit::window::Window>().unwrap();
|
||||
let surface = wgpu::Surface::create(window.deref());
|
||||
let window_size = window.inner_size();
|
||||
(surface, window_size)
|
||||
};
|
||||
|
||||
let swap_chain_descriptor = wgpu::SwapChainDescriptor {
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
width: window_size.width,
|
||||
height: window_size.height,
|
||||
present_mode: wgpu::PresentMode::Vsync,
|
||||
};
|
||||
|
||||
self.swap_chain = Some(device.create_swap_chain(&surface, &swap_chain_descriptor));
|
||||
|
||||
self.data = Some(RenderGraphData::new(
|
||||
device,
|
||||
swap_chain_descriptor,
|
||||
queue,
|
||||
surface,
|
||||
));
|
||||
|
||||
let data = self.data.as_mut().unwrap();
|
||||
for render_resource_manager in self.render_resource_managers.iter_mut() {
|
||||
render_resource_manager.initialize(data, world);
|
||||
if let None = self.pass_pipelines.get(pass) {
|
||||
self.pass_pipelines.insert(pass.to_string(), Vec::new());
|
||||
}
|
||||
|
||||
for pass in self.passes.values_mut() {
|
||||
pass.initialize(data);
|
||||
}
|
||||
|
||||
for pipeline in self.pipelines.values_mut() {
|
||||
pipeline.initialize(data, world);
|
||||
}
|
||||
|
||||
self.resize(window_size.width, window_size.height, world);
|
||||
}
|
||||
|
||||
pub fn render(&mut self, world: &mut World) {
|
||||
if self.passes.len() == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let frame = self
|
||||
.swap_chain
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.get_next_texture()
|
||||
.expect("Timeout when acquiring next swap chain texture");
|
||||
|
||||
let data = self.data.as_mut().unwrap();
|
||||
let mut encoder = data
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
|
||||
for render_resource_manager in self.render_resource_managers.iter_mut() {
|
||||
render_resource_manager.update(data, &mut encoder, world);
|
||||
}
|
||||
|
||||
for (pass_name, pass) in self.passes.iter_mut() {
|
||||
loop {
|
||||
let render_pass = pass.begin(data, world, &mut encoder, &frame);
|
||||
if let Some(mut render_pass) = render_pass {
|
||||
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(data, &mut render_pass, &frame, world);
|
||||
}
|
||||
}
|
||||
|
||||
if !pass.should_repeat() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let command_buffer = encoder.finish();
|
||||
data.queue.submit(&[command_buffer]);
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, width: u32, height: u32, world: &mut World) {
|
||||
let data = self.data.as_mut().unwrap();
|
||||
data.swap_chain_descriptor.width = width;
|
||||
data.swap_chain_descriptor.height = height;
|
||||
self.swap_chain = Some(
|
||||
data.device
|
||||
.create_swap_chain(&data.surface, &data.swap_chain_descriptor),
|
||||
);
|
||||
let mut encoder = data
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
|
||||
for render_resource_manager in self.render_resource_managers.iter_mut() {
|
||||
render_resource_manager.resize(data, &mut encoder, world);
|
||||
}
|
||||
|
||||
let command_buffer = encoder.finish();
|
||||
|
||||
for pass in self.passes.values_mut() {
|
||||
pass.resize(data);
|
||||
}
|
||||
|
||||
for pipeline in self.pipelines.values_mut() {
|
||||
pipeline.resize(data);
|
||||
}
|
||||
|
||||
data.queue.submit(&[command_buffer]);
|
||||
}
|
||||
|
||||
pub fn add_render_resource_manager(
|
||||
&mut self,
|
||||
render_resource_manager: Box<dyn RenderResourceManager>,
|
||||
) {
|
||||
self.render_resource_managers.push(render_resource_manager);
|
||||
}
|
||||
|
||||
pub fn set_pipeline(
|
||||
&mut self,
|
||||
pass_name: &str,
|
||||
pipeline_name: &str,
|
||||
pipeline: Box<dyn Pipeline>,
|
||||
) {
|
||||
self.pipelines.insert(pipeline_name.to_string(), pipeline);
|
||||
if let None = self.pass_pipelines.get_mut(pass_name) {
|
||||
let pipelines = Vec::new();
|
||||
self.pass_pipelines.insert(pass_name.to_string(), pipelines);
|
||||
};
|
||||
|
||||
let current_pass_pipelines = self.pass_pipelines.get_mut(pass_name).unwrap();
|
||||
|
||||
current_pass_pipelines.push(pipeline_name.to_string());
|
||||
}
|
||||
|
||||
pub fn set_pass(&mut self, name: &str, pass: Box<dyn Pass>) {
|
||||
self.passes.insert(name.to_string(), pass);
|
||||
let pass_pipelines = self.pass_pipelines.get_mut(pass).unwrap();
|
||||
pass_pipelines.push(pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RenderGraphBuilder {
|
||||
render_graph: RenderGraph,
|
||||
current_pass: Option<String>,
|
||||
}
|
||||
|
||||
impl RenderGraphBuilder {
|
||||
pub fn new() -> Self {
|
||||
RenderGraphBuilder {
|
||||
render_graph: RenderGraph::default(),
|
||||
current_pass: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_pass(mut self, name: &str, pass: PassDescriptor) -> Self {
|
||||
self.current_pass = Some(name.to_string());
|
||||
self.render_graph
|
||||
.pass_descriptors
|
||||
.insert(name.to_string(), pass);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_pipeline(
|
||||
mut self,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
pipeline: PipelineDescriptor,
|
||||
) -> Self {
|
||||
if let Some(ref pass) = self.current_pass {
|
||||
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
|
||||
self.render_graph
|
||||
.add_pipeline(&pass, pipeline_descriptor_handle);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_pipeline_to_pass(
|
||||
mut self,
|
||||
pass: &str,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
pipeline: PipelineDescriptor,
|
||||
) -> Self {
|
||||
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
|
||||
self.render_graph
|
||||
.add_pipeline(pass, pipeline_descriptor_handle);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_resource_provider(mut self, resource_provider: Box<dyn ResourceProvider>) -> Self {
|
||||
self.render_graph.resource_providers.push(resource_provider);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_texture(mut self, name: &str, texture_descriptor: TextureDescriptor) -> Self {
|
||||
self.render_graph
|
||||
.queued_textures
|
||||
.push((name.to_string(), texture_descriptor));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_draw_target(mut self, name: &str, draw_target: DrawTarget) -> Self {
|
||||
self.render_graph
|
||||
.draw_targets
|
||||
.insert(name.to_string(), draw_target);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> RenderGraph {
|
||||
self.render_graph
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
use crate::render::UniformBuffer;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct RenderGraphData {
|
||||
pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
|
||||
pub device: wgpu::Device,
|
||||
pub queue: wgpu::Queue,
|
||||
pub surface: wgpu::Surface,
|
||||
textures: HashMap<String, wgpu::TextureView>,
|
||||
samplers: HashMap<String, wgpu::Sampler>,
|
||||
uniform_buffers: HashMap<String, UniformBuffer>,
|
||||
bind_group_layouts: HashMap<String, wgpu::BindGroupLayout>,
|
||||
}
|
||||
|
||||
impl RenderGraphData {
|
||||
pub fn new(
|
||||
device: wgpu::Device,
|
||||
swap_chain_descriptor: wgpu::SwapChainDescriptor,
|
||||
queue: wgpu::Queue,
|
||||
surface: wgpu::Surface,
|
||||
) -> Self {
|
||||
RenderGraphData {
|
||||
textures: HashMap::new(),
|
||||
samplers: HashMap::new(),
|
||||
uniform_buffers: HashMap::new(),
|
||||
bind_group_layouts: HashMap::new(),
|
||||
device,
|
||||
swap_chain_descriptor,
|
||||
queue,
|
||||
surface,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_uniform_buffer(&mut self, name: &str, uniform_buffer: UniformBuffer) {
|
||||
self.uniform_buffers
|
||||
.insert(name.to_string(), uniform_buffer);
|
||||
}
|
||||
|
||||
pub fn get_uniform_buffer(&self, name: &str) -> Option<&UniformBuffer> {
|
||||
self.uniform_buffers.get(name)
|
||||
}
|
||||
|
||||
pub fn set_bind_group_layout(&mut self, name: &str, bind_group_layout: wgpu::BindGroupLayout) {
|
||||
self.bind_group_layouts
|
||||
.insert(name.to_string(), bind_group_layout);
|
||||
}
|
||||
|
||||
pub fn get_bind_group_layout(&self, name: &str) -> Option<&wgpu::BindGroupLayout> {
|
||||
self.bind_group_layouts.get(name)
|
||||
}
|
||||
|
||||
pub fn set_texture(&mut self, name: &str, texture: wgpu::TextureView) {
|
||||
self.textures.insert(name.to_string(), texture);
|
||||
}
|
||||
|
||||
pub fn get_texture(&self, name: &str) -> Option<&wgpu::TextureView> {
|
||||
self.textures.get(name)
|
||||
}
|
||||
|
||||
pub fn set_sampler(&mut self, name: &str, sampler: wgpu::Sampler) {
|
||||
self.samplers.insert(name.to_string(), sampler);
|
||||
}
|
||||
|
||||
pub fn get_sampler(&self, name: &str) -> Option<&wgpu::Sampler> {
|
||||
self.samplers.get(name)
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
use crate::render::RenderGraphData;
|
||||
use legion::world::World;
|
||||
|
||||
pub trait RenderResourceManager {
|
||||
fn initialize(&self, render_graph: &mut RenderGraphData, world: &mut World);
|
||||
fn update<'a>(
|
||||
&mut self,
|
||||
render_graph: &mut RenderGraphData,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
world: &mut World,
|
||||
);
|
||||
fn resize<'a>(
|
||||
&self,
|
||||
render_graph: &mut RenderGraphData,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
world: &mut World,
|
||||
);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
render::{render_graph_2::RenderGraph, Shader, ShaderSource},
|
||||
render::{render_graph::RenderGraph, Shader, ShaderSource},
|
||||
};
|
||||
use legion::prelude::*;
|
||||
use std::collections::{HashMap, HashSet};
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
legion::prelude::*,
|
||||
render::render_graph_2::{
|
||||
render::render_graph::{
|
||||
resource::DynamicUniformBufferInfo, PipelineDescriptor, RenderGraph, ResourceInfo,
|
||||
TextureDescriptor,
|
||||
},
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
asset::{AssetStorage, Handle},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
render_graph_2::{
|
||||
render_graph::{
|
||||
resource_name, update_shader_assignments, BindGroup, BindType,
|
||||
DynamicUniformBufferInfo, PassDescriptor, PipelineDescriptor, PipelineLayout,
|
||||
PipelineLayoutType, RenderGraph, RenderPass, RenderPassColorAttachmentDescriptor,
|
||||
|
@ -166,7 +166,7 @@ impl WgpuRenderer {
|
|||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: match fragment_shader {
|
||||
Some(fragment_shader) => Some(wgpu::ProgrammableStageDescriptor {
|
||||
Some(_) => Some(wgpu::ProgrammableStageDescriptor {
|
||||
entry_point: "main",
|
||||
module: fragment_shader_module.as_ref().unwrap(),
|
||||
}),
|
|
@ -1,4 +1,4 @@
|
|||
use crate::render::render_graph_2::Renderer;
|
||||
use crate::render::render_graph::Renderer;
|
||||
use legion::prelude::*;
|
||||
|
||||
pub trait ResourceProvider {
|
|
@ -1,5 +1,5 @@
|
|||
use crate::render::{
|
||||
render_graph_2::{resource_name, Renderer, ResourceProvider},
|
||||
render_graph::{resource_name, Renderer, ResourceProvider},
|
||||
ActiveCamera2d, Camera,
|
||||
};
|
||||
use legion::prelude::*;
|
|
@ -1,5 +1,5 @@
|
|||
use crate::render::{
|
||||
render_graph_2::{resource_name, Renderer, ResourceProvider},
|
||||
render_graph::{resource_name, Renderer, ResourceProvider},
|
||||
ActiveCamera, Camera,
|
||||
};
|
||||
use bevy_transform::prelude::LocalToWorld;
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
prelude::World,
|
||||
render::render_graph_2::{Renderer, ResourceProvider, TextureDescriptor},
|
||||
render::render_graph::{Renderer, ResourceProvider, TextureDescriptor},
|
||||
};
|
||||
|
||||
pub struct FrameTextureResourceProvider {
|
|
@ -1,5 +1,5 @@
|
|||
use crate::render::{
|
||||
render_graph_2::{resource_name, Renderer, ResourceProvider},
|
||||
render_graph::{resource_name, Renderer, ResourceProvider},
|
||||
Light, LightRaw,
|
||||
};
|
||||
use bevy_transform::prelude::{LocalToWorld, Translation};
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
asset::{Asset, AssetStorage, Handle, Mesh, MeshType},
|
||||
ecs, math,
|
||||
prelude::Node,
|
||||
render::render_graph_2::{resource_name, Renderer, ResourceProvider},
|
||||
render::render_graph::{resource_name, Renderer, ResourceProvider},
|
||||
};
|
||||
use bevy_transform::prelude::Parent;
|
||||
use legion::prelude::*;
|
|
@ -1,6 +1,5 @@
|
|||
use crate::{
|
||||
legion::prelude::World,
|
||||
render::render_graph_2::{
|
||||
render::render_graph::{
|
||||
resource::DynamicUniformBufferInfo, AsUniforms, Renderable, Renderer, ResourceProvider,
|
||||
},
|
||||
};
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
prelude::{Entity, World},
|
||||
},
|
||||
math::Vec4,
|
||||
render::render_graph_2::{BindType, UniformPropertyType},
|
||||
render::render_graph::{BindType, UniformPropertyType},
|
||||
};
|
||||
use legion::storage::Component;
|
||||
use zerocopy::AsBytes;
|
|
@ -1,4 +1,4 @@
|
|||
use crate::render::render_graph_2::{
|
||||
use crate::render::render_graph::{
|
||||
uniform::{AsUniforms, UniformInfo},
|
||||
BindType, UniformPropertyType,
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
math,
|
||||
math::Vec4,
|
||||
render::render_graph_2::{
|
||||
render::render_graph::{
|
||||
uniform::{AsUniforms, GetBytes, UniformInfo},
|
||||
BindType, ShaderDefSuffixProvider, UniformPropertyType,
|
||||
},
|
|
@ -1,29 +0,0 @@
|
|||
mod draw_target;
|
||||
pub mod draw_targets;
|
||||
mod pass;
|
||||
pub mod passes;
|
||||
mod pipeline;
|
||||
mod pipeline_layout;
|
||||
pub mod pipelines;
|
||||
mod render_graph;
|
||||
mod renderable;
|
||||
mod renderer;
|
||||
pub mod renderers;
|
||||
mod resource;
|
||||
pub mod resource_name;
|
||||
pub mod resource_provider;
|
||||
pub mod resource_providers;
|
||||
mod uniform;
|
||||
mod uniforms;
|
||||
|
||||
pub use draw_target::*;
|
||||
pub use pass::*;
|
||||
pub use pipeline::*;
|
||||
pub use pipeline_layout::*;
|
||||
pub use render_graph::*;
|
||||
pub use renderable::*;
|
||||
pub use renderer::*;
|
||||
pub use resource::*;
|
||||
pub use resource_provider::*;
|
||||
pub use uniform::*;
|
||||
pub use uniforms::*;
|
|
@ -1,33 +0,0 @@
|
|||
pub struct RenderPassColorAttachmentDescriptor {
|
||||
/// The actual color attachment.
|
||||
pub attachment: String,
|
||||
|
||||
/// The resolve target for this color attachment, if any.
|
||||
pub resolve_target: Option<String>,
|
||||
|
||||
/// The beginning-of-pass load operation for this color attachment.
|
||||
pub load_op: wgpu::LoadOp,
|
||||
|
||||
/// The end-of-pass store operation for this color attachment.
|
||||
pub store_op: wgpu::StoreOp,
|
||||
|
||||
/// The color that will be assigned to every pixel of this attachment when cleared.
|
||||
pub clear_color: wgpu::Color,
|
||||
}
|
||||
|
||||
pub struct RenderPassDepthStencilAttachmentDescriptor {
|
||||
pub attachment: String,
|
||||
pub depth_load_op: wgpu::LoadOp,
|
||||
pub depth_store_op: wgpu::StoreOp,
|
||||
pub clear_depth: f32,
|
||||
pub stencil_load_op: wgpu::LoadOp,
|
||||
pub stencil_store_op: wgpu::StoreOp,
|
||||
pub clear_stencil: u32,
|
||||
}
|
||||
|
||||
// A set of pipeline bindings and draw calls with color and depth outputs
|
||||
pub struct PassDescriptor {
|
||||
pub color_attachments: Vec<RenderPassColorAttachmentDescriptor>,
|
||||
pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachmentDescriptor>,
|
||||
pub sample_count: u32,
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
use crate::{asset::{AssetStorage, Handle}, render::{
|
||||
render_graph_2::{BindGroup, PipelineLayout},
|
||||
shader::{Shader, ShaderStages},
|
||||
}};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VertexBufferDescriptor {
|
||||
pub stride: wgpu::BufferAddress,
|
||||
pub step_mode: wgpu::InputStepMode,
|
||||
pub attributes: Vec<wgpu::VertexAttributeDescriptor>,
|
||||
}
|
||||
|
||||
impl<'a> Into<wgpu::VertexBufferDescriptor<'a>> for &'a VertexBufferDescriptor {
|
||||
fn into(self) -> wgpu::VertexBufferDescriptor<'a> {
|
||||
wgpu::VertexBufferDescriptor {
|
||||
step_mode: self.step_mode,
|
||||
stride: self.stride,
|
||||
attributes: &self.attributes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PipelineLayoutType {
|
||||
Manual(PipelineLayout),
|
||||
Reflected(Option<PipelineLayout>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PipelineDescriptor {
|
||||
pub draw_targets: Vec<String>,
|
||||
pub layout: PipelineLayoutType,
|
||||
pub shader_stages: ShaderStages,
|
||||
pub rasterization_state: Option<wgpu::RasterizationStateDescriptor>,
|
||||
|
||||
/// The primitive topology used to interpret vertices.
|
||||
pub primitive_topology: wgpu::PrimitiveTopology,
|
||||
|
||||
/// The effect of draw calls on the color aspect of the output target.
|
||||
pub color_states: Vec<wgpu::ColorStateDescriptor>,
|
||||
|
||||
/// The effect of draw calls on the depth and stencil aspects of the output target, if any.
|
||||
pub depth_stencil_state: Option<wgpu::DepthStencilStateDescriptor>,
|
||||
|
||||
/// The format of any index buffers used with this pipeline.
|
||||
pub index_format: wgpu::IndexFormat,
|
||||
|
||||
/// The format of any vertex buffers used with this pipeline.
|
||||
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>,
|
||||
|
||||
/// The number of samples calculated per pixel (for MSAA).
|
||||
pub sample_count: u32,
|
||||
|
||||
/// Bitmask that restricts the samples of a pixel modified by this pipeline.
|
||||
pub sample_mask: u32,
|
||||
|
||||
/// When enabled, produces another sample mask per pixel based on the alpha output value, that
|
||||
/// is ANDed with the sample_mask and the primitive coverage to restrict the set of samples
|
||||
/// affected by a primitive.
|
||||
/// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
|
||||
/// is guaranteed to be all 1-s.
|
||||
pub alpha_to_coverage_enabled: bool,
|
||||
}
|
||||
|
||||
impl PipelineDescriptor {
|
||||
fn new(vertex_shader: Handle<Shader>) -> Self {
|
||||
PipelineDescriptor {
|
||||
layout: PipelineLayoutType::Reflected(None),
|
||||
color_states: Vec::new(),
|
||||
depth_stencil_state: None,
|
||||
draw_targets: Vec::new(),
|
||||
shader_stages: ShaderStages::new(vertex_shader),
|
||||
vertex_buffer_descriptors: Vec::new(),
|
||||
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_layout(&self) -> Option<&PipelineLayout> {
|
||||
match self.layout {
|
||||
PipelineLayoutType::Reflected(ref layout) => layout.as_ref(),
|
||||
PipelineLayoutType::Manual(ref layout) => Some(layout),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_layout_mut(&mut self) -> Option<&mut PipelineLayout> {
|
||||
match self.layout {
|
||||
PipelineLayoutType::Reflected(ref mut layout) => layout.as_mut(),
|
||||
PipelineLayoutType::Manual(ref mut layout) => Some(layout),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PipelineDescriptor {
|
||||
pub fn build(shader_storage: &mut AssetStorage<Shader>, vertex_shader: Shader) -> PipelineBuilder {
|
||||
PipelineBuilder::new(shader_storage, vertex_shader)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PipelineBuilder<'a> {
|
||||
pipeline: PipelineDescriptor,
|
||||
shader_storage: &'a mut AssetStorage<Shader>,
|
||||
}
|
||||
|
||||
impl<'a> PipelineBuilder<'a> {
|
||||
pub fn new(shader_storage: &'a mut AssetStorage<Shader>, vertex_shader: Shader) -> Self {
|
||||
let vertex_shader_handle = shader_storage.add(vertex_shader);
|
||||
PipelineBuilder {
|
||||
pipeline: PipelineDescriptor::new(vertex_shader_handle),
|
||||
shader_storage,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(self) -> PipelineDescriptor {
|
||||
self.pipeline
|
||||
}
|
||||
|
||||
pub fn with_fragment_shader(mut self, fragment_shader: Shader) -> Self {
|
||||
let fragment_shader_handle = self.shader_storage.add(fragment_shader);
|
||||
self.pipeline.shader_stages.fragment = Some(fragment_shader_handle);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_color_state(mut self, color_state_descriptor: wgpu::ColorStateDescriptor) -> Self {
|
||||
self.pipeline.color_states.push(color_state_descriptor);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_depth_stencil_state(
|
||||
mut self,
|
||||
depth_stencil_state: wgpu::DepthStencilStateDescriptor,
|
||||
) -> Self {
|
||||
if let Some(_) = self.pipeline.depth_stencil_state {
|
||||
panic!("Depth stencil state has already been set");
|
||||
}
|
||||
self.pipeline.depth_stencil_state = Some(depth_stencil_state);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_bind_group(mut self, bind_group: BindGroup) -> Self {
|
||||
if let PipelineLayoutType::Reflected(_) = self.pipeline.layout {
|
||||
self.pipeline.layout = PipelineLayoutType::Manual(PipelineLayout::new());
|
||||
}
|
||||
|
||||
if let PipelineLayoutType::Manual(ref mut layout) = self.pipeline.layout {
|
||||
layout.bind_groups.push(bind_group);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_vertex_buffer_descriptor(
|
||||
mut self,
|
||||
vertex_buffer_descriptor: VertexBufferDescriptor,
|
||||
) -> Self {
|
||||
self.pipeline
|
||||
.vertex_buffer_descriptors
|
||||
.push(vertex_buffer_descriptor);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_index_format(mut self, index_format: wgpu::IndexFormat) -> Self {
|
||||
self.pipeline.index_format = index_format;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_draw_target(mut self, name: &str) -> Self {
|
||||
self.pipeline.draw_targets.push(name.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_rasterization_state(
|
||||
mut self,
|
||||
rasterization_state: wgpu::RasterizationStateDescriptor,
|
||||
) -> Self {
|
||||
self.pipeline.rasterization_state = Some(rasterization_state);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_primitive_topology(mut self, primitive_topology: wgpu::PrimitiveTopology) -> Self {
|
||||
self.pipeline.primitive_topology = primitive_topology;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_sample_count(mut self, sample_count: u32) -> Self {
|
||||
self.pipeline.sample_count = sample_count;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_alpha_to_coverage_enabled(mut self, alpha_to_coverage_enabled: bool) -> Self {
|
||||
self.pipeline.alpha_to_coverage_enabled = alpha_to_coverage_enabled;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_sample_mask(mut self, sample_mask: u32) -> Self {
|
||||
self.pipeline.sample_mask = sample_mask;
|
||||
self
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 v_Color;
|
||||
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
|
||||
void main() {
|
||||
o_Target = v_Color;
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
render::render_graph_2::{
|
||||
DrawTarget, PassDescriptor, PipelineDescriptor, ResourceProvider, TextureDescriptor,
|
||||
},
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub struct RenderGraph {
|
||||
pub pipeline_descriptors: HashSet<Handle<PipelineDescriptor>>,
|
||||
// TODO: make this ordered
|
||||
pub pass_descriptors: HashMap<String, PassDescriptor>,
|
||||
pub pass_pipelines: HashMap<String, Vec<Handle<PipelineDescriptor>>>,
|
||||
pub resource_providers: Vec<Box<dyn ResourceProvider>>,
|
||||
pub queued_textures: Vec<(String, TextureDescriptor)>,
|
||||
pub draw_targets: HashMap<String, DrawTarget>,
|
||||
}
|
||||
|
||||
impl Default for RenderGraph {
|
||||
fn default() -> Self {
|
||||
RenderGraph {
|
||||
pipeline_descriptors: HashSet::new(),
|
||||
pass_descriptors: HashMap::new(),
|
||||
pass_pipelines: HashMap::new(),
|
||||
resource_providers: Vec::new(),
|
||||
queued_textures: Vec::new(),
|
||||
draw_targets: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderGraph {
|
||||
pub fn add_pipeline(&mut self, pass: &str, pipeline: Handle<PipelineDescriptor>) {
|
||||
self.pipeline_descriptors.insert(pipeline.clone());
|
||||
|
||||
if let None = self.pass_pipelines.get(pass) {
|
||||
self.pass_pipelines.insert(pass.to_string(), Vec::new());
|
||||
}
|
||||
|
||||
let pass_pipelines = self.pass_pipelines.get_mut(pass).unwrap();
|
||||
pass_pipelines.push(pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RenderGraphBuilder {
|
||||
render_graph: RenderGraph,
|
||||
current_pass: Option<String>,
|
||||
}
|
||||
|
||||
impl RenderGraphBuilder {
|
||||
pub fn new() -> Self {
|
||||
RenderGraphBuilder {
|
||||
render_graph: RenderGraph::default(),
|
||||
current_pass: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_pass(mut self, name: &str, pass: PassDescriptor) -> Self {
|
||||
self.current_pass = Some(name.to_string());
|
||||
self.render_graph
|
||||
.pass_descriptors
|
||||
.insert(name.to_string(), pass);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_pipeline(
|
||||
mut self,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
pipeline: PipelineDescriptor,
|
||||
) -> Self {
|
||||
if let Some(ref pass) = self.current_pass {
|
||||
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
|
||||
self.render_graph
|
||||
.add_pipeline(&pass, pipeline_descriptor_handle);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_pipeline_to_pass(
|
||||
mut self,
|
||||
pass: &str,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
pipeline: PipelineDescriptor,
|
||||
) -> Self {
|
||||
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
|
||||
self.render_graph
|
||||
.add_pipeline(pass, pipeline_descriptor_handle);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_resource_provider(mut self, resource_provider: Box<dyn ResourceProvider>) -> Self {
|
||||
self.render_graph.resource_providers.push(resource_provider);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_texture(mut self, name: &str, texture_descriptor: TextureDescriptor) -> Self {
|
||||
self.render_graph
|
||||
.queued_textures
|
||||
.push((name.to_string(), texture_descriptor));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_draw_target(mut self, name: &str, draw_target: DrawTarget) -> Self {
|
||||
self.render_graph
|
||||
.draw_targets
|
||||
.insert(name.to_string(), draw_target);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> RenderGraph {
|
||||
self.render_graph
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
use crate::{math, render::*};
|
||||
|
||||
use legion::prelude::*;
|
||||
use std::mem;
|
||||
use zerocopy::{AsBytes, FromBytes};
|
||||
|
||||
pub const GLOBAL_2D_UNIFORM_BUFFER_NAME: &str = "global_2d";
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
pub struct Global2dUniforms {
|
||||
pub projection_matrix: [[f32; 4]; 4],
|
||||
}
|
||||
|
||||
pub struct Global2dResourceManager;
|
||||
|
||||
impl RenderResourceManager for Global2dResourceManager {
|
||||
fn initialize(&self, render_graph: &mut RenderGraphData, _: &mut World) {
|
||||
let uniform_size = mem::size_of::<Global2dUniforms>() as wgpu::BufferAddress;
|
||||
let ui_uniforms = Global2dUniforms {
|
||||
projection_matrix: math::Mat4::identity().to_cols_array_2d(),
|
||||
};
|
||||
|
||||
let buffer = render_graph.device.create_buffer_with_data(
|
||||
ui_uniforms.as_bytes(),
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
|
||||
let uniform_buffer = UniformBuffer {
|
||||
buffer,
|
||||
size: uniform_size,
|
||||
};
|
||||
render_graph.set_uniform_buffer(GLOBAL_2D_UNIFORM_BUFFER_NAME, uniform_buffer);
|
||||
}
|
||||
|
||||
fn update<'a>(
|
||||
&mut self,
|
||||
_render_graph: &mut RenderGraphData,
|
||||
_encoder: &'a mut wgpu::CommandEncoder,
|
||||
_world: &mut World,
|
||||
) {
|
||||
}
|
||||
|
||||
fn resize<'a>(
|
||||
&self,
|
||||
render_graph: &mut RenderGraphData,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
world: &mut World,
|
||||
) {
|
||||
for (mut camera, _) in <(Write<Camera>, Read<ActiveCamera2d>)>::query().iter_mut(world) {
|
||||
camera.update(
|
||||
render_graph.swap_chain_descriptor.width,
|
||||
render_graph.swap_chain_descriptor.height,
|
||||
);
|
||||
let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d();
|
||||
let matrix_size = mem::size_of::<[[f32; 4]; 4]>() as u64;
|
||||
let temp_camera_buffer = render_graph
|
||||
.device
|
||||
.create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::COPY_SRC);
|
||||
let global_2d_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(GLOBAL_2D_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
encoder.copy_buffer_to_buffer(
|
||||
&temp_camera_buffer,
|
||||
0,
|
||||
&global_2d_uniform_buffer.buffer,
|
||||
0,
|
||||
matrix_size,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
use crate::{
|
||||
math,
|
||||
prelude::LocalToWorld,
|
||||
render::{passes::ForwardUniforms, *},
|
||||
};
|
||||
|
||||
use legion::prelude::*;
|
||||
use std::mem;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub const FORWARD_UNIFORM_BUFFER_NAME: &str = "forward";
|
||||
|
||||
pub struct GlobalResourceManager;
|
||||
|
||||
impl RenderResourceManager for GlobalResourceManager {
|
||||
fn initialize(&self, render_graph: &mut RenderGraphData, world: &mut World) {
|
||||
let light_count = <Read<Light>>::query().iter(world).count();
|
||||
let forward_uniforms = ForwardUniforms {
|
||||
proj: math::Mat4::identity().to_cols_array_2d(),
|
||||
num_lights: [light_count as u32, 0, 0, 0],
|
||||
};
|
||||
|
||||
let uniform_size = mem::size_of::<ForwardUniforms>() as wgpu::BufferAddress;
|
||||
let buffer = render_graph.device.create_buffer_with_data(
|
||||
forward_uniforms.as_bytes(),
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
|
||||
let uniform_buffer = UniformBuffer {
|
||||
buffer,
|
||||
size: uniform_size,
|
||||
};
|
||||
render_graph.set_uniform_buffer(FORWARD_UNIFORM_BUFFER_NAME, uniform_buffer);
|
||||
}
|
||||
fn update<'a>(
|
||||
&mut self,
|
||||
_render_graph: &mut RenderGraphData,
|
||||
_encoder: &'a mut wgpu::CommandEncoder,
|
||||
_world: &mut World,
|
||||
) {
|
||||
}
|
||||
fn resize<'a>(
|
||||
&self,
|
||||
render_graph: &mut RenderGraphData,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
world: &mut World,
|
||||
) {
|
||||
for (mut camera, local_to_world, _) in
|
||||
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
|
||||
{
|
||||
camera.update(
|
||||
render_graph.swap_chain_descriptor.width,
|
||||
render_graph.swap_chain_descriptor.height,
|
||||
);
|
||||
let camera_matrix: [[f32; 4]; 4] =
|
||||
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
|
||||
let matrix_size = mem::size_of::<[[f32; 4]; 4]>() as u64;
|
||||
let temp_camera_buffer = render_graph
|
||||
.device
|
||||
.create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::COPY_SRC);
|
||||
let forward_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(FORWARD_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
encoder.copy_buffer_to_buffer(
|
||||
&temp_camera_buffer,
|
||||
0,
|
||||
&forward_uniform_buffer.buffer,
|
||||
0,
|
||||
matrix_size,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
use crate::{
|
||||
prelude::{LocalToWorld, Translation},
|
||||
render::*,
|
||||
};
|
||||
|
||||
use legion::prelude::*;
|
||||
use std::mem;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub const LIGHT_UNIFORM_BUFFER_NAME: &str = "lights";
|
||||
|
||||
pub struct LightResourceManager {
|
||||
pub lights_are_dirty: bool,
|
||||
pub max_lights: usize,
|
||||
}
|
||||
|
||||
impl LightResourceManager {
|
||||
pub fn new(max_lights: usize) -> Self {
|
||||
LightResourceManager {
|
||||
lights_are_dirty: true,
|
||||
max_lights,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderResourceManager for LightResourceManager {
|
||||
fn initialize(&self, render_graph: &mut RenderGraphData, _world: &mut World) {
|
||||
let light_uniform_size =
|
||||
(self.max_lights * mem::size_of::<LightRaw>()) as wgpu::BufferAddress;
|
||||
|
||||
let light_uniform_buffer = UniformBuffer {
|
||||
buffer: render_graph.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size: light_uniform_size,
|
||||
usage: wgpu::BufferUsage::UNIFORM
|
||||
| wgpu::BufferUsage::COPY_SRC
|
||||
| wgpu::BufferUsage::COPY_DST,
|
||||
}),
|
||||
size: light_uniform_size,
|
||||
};
|
||||
|
||||
render_graph.set_uniform_buffer(LIGHT_UNIFORM_BUFFER_NAME, light_uniform_buffer);
|
||||
}
|
||||
fn update<'a>(
|
||||
&mut self,
|
||||
render_graph: &mut RenderGraphData,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
world: &mut World,
|
||||
) {
|
||||
if self.lights_are_dirty {
|
||||
let 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;
|
||||
let temp_buf_data = render_graph
|
||||
.device
|
||||
.create_buffer_mapped(total_size, wgpu::BufferUsage::COPY_SRC);
|
||||
for ((light, local_to_world, translation), slot) in light_query
|
||||
.iter(world)
|
||||
.zip(temp_buf_data.data.chunks_exact_mut(size))
|
||||
{
|
||||
slot.copy_from_slice(
|
||||
LightRaw::from(&light, &local_to_world.0, &translation).as_bytes(),
|
||||
);
|
||||
}
|
||||
|
||||
let light_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(LIGHT_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
encoder.copy_buffer_to_buffer(
|
||||
&temp_buf_data.finish(),
|
||||
0,
|
||||
&light_uniform_buffer.buffer,
|
||||
0,
|
||||
total_size as wgpu::BufferAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
fn resize<'a>(
|
||||
&self,
|
||||
_render_graph: &mut RenderGraphData,
|
||||
_encoder: &'a mut wgpu::CommandEncoder,
|
||||
_world: &mut World,
|
||||
) {
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
use crate::{prelude::LocalToWorld, render::*};
|
||||
|
||||
use legion::prelude::*;
|
||||
use std::mem;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub const MATERIAL_BIND_GROUP_LAYOUT_NAME: &str = "material";
|
||||
|
||||
pub struct MaterialResourceManager;
|
||||
|
||||
impl RenderResourceManager for MaterialResourceManager {
|
||||
fn initialize(&self, render_graph: &mut RenderGraphData, _world: &mut World) {
|
||||
let material_bind_group_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[wgpu::BindGroupLayoutBinding {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
}],
|
||||
});
|
||||
|
||||
render_graph
|
||||
.set_bind_group_layout(MATERIAL_BIND_GROUP_LAYOUT_NAME, material_bind_group_layout);
|
||||
}
|
||||
|
||||
fn update<'a>(
|
||||
&mut self,
|
||||
render_graph: &mut RenderGraphData,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
world: &mut World,
|
||||
) {
|
||||
let entities =
|
||||
<(Write<Material>, Read<LocalToWorld>)>::query().filter(!component::<Instanced>());
|
||||
let entities_count = entities.iter_mut(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);
|
||||
|
||||
for ((material, transform), slot) in entities
|
||||
.iter_mut(world)
|
||||
.zip(temp_buf_data.data.chunks_exact_mut(size))
|
||||
{
|
||||
slot.copy_from_slice(
|
||||
MaterialUniforms {
|
||||
model: transform.0.to_cols_array_2d(),
|
||||
color: material.get_color().into(),
|
||||
}
|
||||
.as_bytes(),
|
||||
);
|
||||
}
|
||||
|
||||
let material_bind_group_layout = render_graph
|
||||
.get_bind_group_layout(MATERIAL_BIND_GROUP_LAYOUT_NAME)
|
||||
.unwrap();
|
||||
|
||||
for mut material in <Write<Material>>::query()
|
||||
.filter(!component::<Instanced>())
|
||||
.iter_mut(world)
|
||||
{
|
||||
if let None = material.bind_group {
|
||||
let material_uniform_size =
|
||||
mem::size_of::<MaterialUniforms>() as wgpu::BufferAddress;
|
||||
let uniform_buf = render_graph.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size: material_uniform_size,
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
});
|
||||
|
||||
let bind_group =
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: material_bind_group_layout,
|
||||
bindings: &[wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer {
|
||||
buffer: &uniform_buf,
|
||||
range: 0..material_uniform_size,
|
||||
},
|
||||
}],
|
||||
});
|
||||
|
||||
material.bind_group = Some(bind_group);
|
||||
material.uniform_buf = Some(uniform_buf);
|
||||
}
|
||||
}
|
||||
|
||||
let temp_buf = temp_buf_data.finish();
|
||||
for (i, (material, _)) in entities.iter_mut(world).enumerate() {
|
||||
encoder.copy_buffer_to_buffer(
|
||||
&temp_buf,
|
||||
(i * size) as wgpu::BufferAddress,
|
||||
material.uniform_buf.as_ref().unwrap(),
|
||||
0,
|
||||
size as wgpu::BufferAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
fn resize<'a>(
|
||||
&self,
|
||||
_render_graph: &mut RenderGraphData,
|
||||
_encoder: &'a mut wgpu::CommandEncoder,
|
||||
_world: &mut World,
|
||||
) {
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
mod global_2d_resource_manager;
|
||||
mod global_resource_manager;
|
||||
mod light_resource_manager;
|
||||
mod material_resource_manager;
|
||||
|
||||
pub use global_2d_resource_manager::*;
|
||||
pub use global_resource_manager::*;
|
||||
pub use light_resource_manager::*;
|
||||
pub use material_resource_manager::*;
|
|
@ -1,4 +1,4 @@
|
|||
use crate::render::render_graph_2::{
|
||||
use crate::render::render_graph::{
|
||||
BindGroup, BindType, Binding, UniformProperty, UniformPropertyType,
|
||||
};
|
||||
use spirv_reflect::{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::render::render_graph_2::VertexBufferDescriptor;
|
||||
use crate::render::render_graph::VertexBufferDescriptor;
|
||||
use std::convert::From;
|
||||
use zerocopy::{AsBytes, FromBytes};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue