use std::time::Instant; use floating_duration::TimeAsFloat; use glium::{ glutin::{ self, dpi::PhysicalSize, event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }, Surface, }; use nalgebra as na; use rendology::{ basic_obj, BasicObj, Instancing, InstancingMode, Light, Mesh, RenderList, ShadedScenePass, ShadedScenePassSetup, ShadowPass, }; const WINDOW_SIZE: (u32, u32) = (1280, 720); #[derive(Default)] struct Scene { cubes: RenderList, lights: Vec, } struct Pipeline { rendology: rendology::Pipeline, shadow_pass: Option>, scene_pass: ShadedScenePass, cube: Mesh, cube_instancing: Instancing, } impl Pipeline { fn create( facade: &F, config: &rendology::Config, ) -> Result { let rendology = rendology::Pipeline::create(facade, config, WINDOW_SIZE)?; let shadow_pass = rendology.create_shadow_pass(facade, basic_obj::Core, InstancingMode::Vertex)?; let scene_pass = rendology.create_shaded_scene_pass( facade, basic_obj::Core, InstancingMode::Vertex, ShadedScenePassSetup { draw_shadowed: true, draw_glowing: false, }, )?; let cube = BasicObj::Cube.create_mesh(facade)?; let cube_instancing = Instancing::create(facade)?; Ok(Pipeline { rendology, shadow_pass, scene_pass, cube, cube_instancing, }) } fn draw_frame( &mut self, facade: &F, context: &rendology::Context, scene: &Scene, target: &mut S, ) -> Result<(), rendology::DrawError> { self.cube_instancing .update(facade, scene.cubes.as_slice())?; let draw_params = glium::DrawParameters { backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockwise, ..Default::default() }; self.rendology .start_frame(facade, (0.0, 0.0, 0.0), context.clone(), target)? .shadow_pass() .draw( &self.shadow_pass, &self.cube_instancing.as_drawable(&self.cube), &(), &draw_params, )? .shaded_scene_pass() .draw( &self.scene_pass, &self.cube_instancing.as_drawable(&self.cube), &(), &draw_params, )? .compose(&scene.lights)? .postprocess()? .present() } } fn main() { simple_logger::init_with_level(log::Level::Info).unwrap(); // Initialize glium let events_loop = EventLoop::new(); let display = { let window_builder = WindowBuilder::new() .with_inner_size(PhysicalSize::new(WINDOW_SIZE.0, WINDOW_SIZE.1)) .with_title("Rendology example: Cube"); let context_builder = glutin::ContextBuilder::new(); glium::Display::new(window_builder, context_builder, &events_loop).unwrap() }; // Initialize rendology pipeline let mut pipeline = Pipeline::create(&display, &Default::default()).unwrap(); let start_time = Instant::now(); events_loop.run(move |event, _, control_flow| { *control_flow = ControlFlow::Poll; match event { Event::LoopDestroyed => return, Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => { *control_flow = ControlFlow::Exit; return }, _ => (), }, _ => (), } let time = start_time.elapsed().as_fractional_secs() as f32; let scene = scene(time); let mut target = display.draw(); let render_context = render_context(target.get_dimensions()); pipeline .draw_frame(&display, &render_context, &scene, &mut target) .unwrap(); target.finish().unwrap(); }); } fn scene(time: f32) -> Scene { let mut scene = Scene::default(); scene.cubes.add(basic_obj::Instance { transform: na::Matrix4::new_translation(&na::Vector3::new(0.0, 0.0, 3.0)) * na::Matrix4::from_euler_angles(time, time, time), color: na::Vector4::new(0.9, 0.9, 0.9, 1.0), }); scene.cubes.add(basic_obj::Instance { transform: na::Matrix4::new_nonuniform_scaling(&na::Vector3::new(10.0, 10.0, 0.1)), color: na::Vector4::new(0.0, 1.0, 0.0, 1.0), }); scene.lights.push(Light { position: na::Point3::new(10.0, 10.0, 10.0), attenuation: na::Vector4::new(1.0, 0.0, 0.0, 0.0), color: na::Vector3::new(1.0, 1.0, 1.0), is_main: true, ..Default::default() }); scene } fn render_context(target_size: (u32, u32)) -> rendology::Context { let camera = rendology::Camera { view: na::Matrix4::look_at_rh( &na::Point3::new(9.0, -5.0, 7.0), &na::Point3::new(0.0, 0.0, 0.0), &na::Vector3::new(0.0, 0.0, 1.0), ), projection: na::Perspective3::new( target_size.0 as f32 / target_size.1 as f32, 60.0f32.to_radians(), 0.1, 1000.0, ) .to_homogeneous(), viewport_size: na::Vector2::new(target_size.0 as f32, target_size.1 as f32), }; rendology::Context { camera, main_light_pos: na::Point3::new(10.0, 10.0, 10.0), main_light_center: na::Point3::new(0.0, 0.0, 0.0), ambient_light: na::Vector3::new(0.3, 0.3, 0.3), } }