98 lines
3.0 KiB
Rust
98 lines
3.0 KiB
Rust
//! [Legion](https://github.com/amethyst/legion) integration.
|
|
|
|
use crate::camera::Camera;
|
|
use crate::pass::{self, debug, mesh};
|
|
use crate::scene;
|
|
use crate::viewport::{ViewportInfo, WinitViewport};
|
|
use crate::Renderer;
|
|
use legion::systems::Builder;
|
|
use legion::world::SubWorld;
|
|
use legion::*;
|
|
use std::sync::Arc;
|
|
|
|
/// Initializes the Cyborg renderer within a Legion world.
|
|
///
|
|
/// Uses the provided [Builder] to run all rendering code.
|
|
///
|
|
/// Required pre-initialized resources:
|
|
/// - [Renderer]
|
|
/// - [ViewportInfo] (TODO: dynamic viewport targeting)
|
|
/// - [mesh::ShaderInfo]
|
|
pub fn build_renderer(resources: &mut Resources, builder: &mut Builder) {
|
|
let renderer = resources.get_mut::<Renderer>().unwrap();
|
|
let viewport_info = resources.get::<ViewportInfo>().unwrap();
|
|
let mesh_shaders = resources.get::<mesh::ShaderInfo>().unwrap();
|
|
|
|
let device = renderer.get_device();
|
|
let layouts = renderer.get_layouts();
|
|
|
|
let mesh_pass = mesh::MeshPass::new(
|
|
device.to_owned(),
|
|
layouts.to_owned(),
|
|
viewport_info.to_owned(),
|
|
mesh_shaders.to_owned(),
|
|
);
|
|
|
|
let debug_pass = debug::DebugPass::new(
|
|
device.to_owned(),
|
|
layouts.to_owned(),
|
|
viewport_info.to_owned(),
|
|
);
|
|
|
|
let frames_in_flight = renderer.get_frames_in_flight();
|
|
let mesh_pass = pass::RenderPassBox::new(Arc::new(mesh_pass), frames_in_flight);
|
|
let debug_pass = pass::RenderPassBox::new(Arc::new(debug_pass), frames_in_flight);
|
|
|
|
// drop borrowed resources so that new ones can be inserted
|
|
drop(renderer);
|
|
drop(viewport_info);
|
|
drop(mesh_shaders);
|
|
|
|
resources.insert(mesh_pass);
|
|
resources.insert(debug_pass);
|
|
|
|
builder.add_system(draw_transformed_meshes_system());
|
|
builder.add_system(render_system());
|
|
builder.add_system(present_winit_system());
|
|
}
|
|
|
|
#[system]
|
|
#[read_component(WinitViewport)]
|
|
#[read_component(Camera)]
|
|
fn render(
|
|
world: &mut SubWorld,
|
|
#[resource] renderer: &mut Renderer,
|
|
#[resource] mesh_pass: &mut pass::RenderPassBox<mesh::MeshPass>,
|
|
#[resource] debug_pass: &mut pass::RenderPassBox<debug::DebugPass>,
|
|
) {
|
|
let target_query: Vec<_> = <(&WinitViewport, &Camera)>::query().iter(world).collect();
|
|
if target_query.len() > 1 {
|
|
eprintln!("Cyborg does not currently support more than one viewport at a time!");
|
|
return;
|
|
} else if let Some((viewport, camera)) = target_query.get(0) {
|
|
let mut passes: Vec<&mut dyn pass::RenderPassBoxTrait> = Vec::new();
|
|
passes.push(mesh_pass);
|
|
passes.push(debug_pass);
|
|
renderer.render(passes.as_mut_slice(), *viewport, camera);
|
|
}
|
|
}
|
|
|
|
#[system]
|
|
fn draw_transformed_meshes(
|
|
#[resource] mesh_pass: &pass::RenderPassBox<mesh::MeshPass>,
|
|
world: &mut SubWorld,
|
|
query: &mut Query<&scene::TransformedMesh>,
|
|
) {
|
|
let transformed: Vec<_> = query.iter(world).map(|m| m.clone()).collect();
|
|
mesh_pass
|
|
.get_meshes()
|
|
.write()
|
|
.transformed
|
|
.extend_from_slice(transformed.as_slice());
|
|
}
|
|
|
|
#[system(for_each)]
|
|
fn present_winit(viewport: &mut WinitViewport) {
|
|
viewport.present();
|
|
}
|