extern crate gl; extern crate env_logger; #[macro_use] extern crate log; #[macro_use] extern crate gfx; extern crate gfx_device_gl; extern crate openvr as vr; extern crate piston_window; use gfx::{tex, CombinedError, Device, Factory, Typed}; use gfx::traits::FactoryExt; use piston_window::{PistonWindow, Window, WindowSettings}; pub type ColorFormat = gfx::format::Srgba8; //pub type DepthFormat = gfx::format::DepthStencil; gfx_defines!{ vertex Vertex { pos: [f32; 2] = "a_pos", color: [f32; 3] = "a_color", } pipeline pipe { vbuf: gfx::VertexBuffer = (), pixcolor: gfx::RenderTarget = "pixcolor", } } const TRIANGLE: [Vertex; 3] = [ Vertex { pos: [ -0.5, -0.5 ], color: [1.0, 0.0, 0.0] }, Vertex { pos: [ 0.5, -0.5 ], color: [0.0, 1.0, 0.0] }, Vertex { pos: [ 0.0, 0.5 ], color: [0.0, 0.0, 1.0] } ]; fn main() { env_logger::init().expect("env logger"); let system = vr::init().expect("OpenVR init"); let compositor = vr::compositor().expect("OpenVR Compositor"); let render_size = system.recommended_render_target_size(); let mut window: PistonWindow = WindowSettings::new("Hello Virtual World!", [512; 2]) .exit_on_esc(true) .vsync(false) //.vsync(true) .build().expect("Building Window"); info!("monitor target: {:?}", window.output_color.raw()); /* let _sysleft = system.projection_matrix(vr::Eye::Left, 0.01, 1000.0); let _eyeleft = system.eye_to_head_transform(vr::Eye::Left); let _sysright = system.projection_matrix(vr::Eye::Right, 0.01, 1000.0); let _eyeright = system.eye_to_head_transform(vr::Eye::Right); */ let pso = window.factory.create_pipeline_simple(VERTEX_SHADER_SRC, FRAGMENT_SHADER_SRC, pipe::new()) .expect("create pipeline"); let (tex_left, tgt_left) = create_renderbuffer_target::(&mut window.factory, render_size.width as tex::Size, render_size.height as tex::Size) .expect("create left renderbuffer"); let (tex_right, tgt_right) = create_renderbuffer_target(&mut window.factory, render_size.width as tex::Size, render_size.height as tex::Size) .expect("create right renderbuffer"); let (vertex_buffer, slice) = window.factory.create_vertex_buffer_with_slice(&TRIANGLE, ()); let pipe_monitor = pipe::Data { vbuf: vertex_buffer.clone(), pixcolor: window.output_color.clone(), }; let pipe_left = pipe::Data { vbuf: vertex_buffer.clone(), pixcolor: tgt_left, }; let pipe_right = pipe::Data { vbuf: vertex_buffer.clone(), pixcolor: tgt_right, }; let mut frame = 0; let mut manager = gfx::handle::Manager::new(); window.window.swap_buffers(); frame += 1; // To contain setup calls to Frame 0 in apitrace 'main: //while let Some(_) = window.next() { loop { info!("Frame #{}", frame); let _now = std::time::SystemTime::now(); // Get the current sensor state let _poses = compositor.wait_get_poses(); manager.clear(); trace!("\t{:?} got pose", _now.elapsed()); if frame % 90 == 0 { warn!("\t#{}: poses: {:?}\n", frame, _poses.poses[0]); } frame += 1; for pass in [(Some((vr::Eye::Left, &tex_left)), &pipe_left), (Some((vr::Eye::Right, &tex_right)), &pipe_right), (None, &pipe_monitor),] .into_iter() { info!("\tpass for eye: {:?}", pass.0); window.encoder.clear(&pass.1.pixcolor, [0.1, 0.5, 0.1, 1.0]); window.encoder.draw(&slice, &pso, pass.1); window.encoder.flush(&mut window.device); // Submit eye textures if let Some((eye, tex)) = pass.0 { let tex_id = match manager.ref_texture(tex.raw()) { &gfx_device_gl::NewTexture::Surface(id) => id, _ => panic!("Not a surface") }; info!("\t\tUsing texture id #{} for target {:?}", tex_id, pass.1.pixcolor.raw()); check_err(&mut window.device); gl_debug(&mut window.device, b"before"); compositor.submit(eye, tex_id as usize, vr::common::TextureBounds::new((0.0, 1.0), (0.0, 1.0))); trace!("\t\t{:?} submit {:?}", _now.elapsed(), eye); gl_debug(&mut window.device, b"after!"); check_err(&mut window.device); } else { window.window.swap_buffers(); } } window.device.cleanup(); // handle window events while let Some(ev) = window.poll_event() { match ev { piston_window::Input::Text(_) => break 'main, _ => debug!("\t{:?}", ev) } } } info!("shutting down"); vr::shutdown() } fn create_renderbuffer_target(factory: &mut gfx_device_gl::Factory, width: tex::Size, height: tex::Size) -> Result<(gfx::handle::Texture, gfx::handle::RenderTargetView), gfx::CombinedError> where T: gfx::format::RenderFormat + gfx::format::TextureFormat { let tex = try!(factory.create_texture( tex::Kind::D2(width, height, tex::AaMode::Single), 1, // levels gfx::RENDER_TARGET, // bind gfx::Usage::GpuOnly, // Usage Some(::get_channel_type()))); // hint: format::ChannelType? let tgt = try!(factory.view_texture_as_render_target(&tex, 0, None)); Ok((tex, tgt)) } fn gl_debug(device: &mut gfx_device_gl::Device, msg: &'static [u8; 6]) { unsafe { device.with_gl_naked(|gl| { gl.DebugMessageInsert(gl::DEBUG_SOURCE_APPLICATION, gl::DEBUG_TYPE_OTHER, 0, gl::DEBUG_SEVERITY_LOW, msg.len() as i32, std::mem::transmute(msg)); }); } } fn check_err(device: &mut gfx_device_gl::Device) { unsafe { device.with_gl_naked(|gl| { let err: gl::types::GLenum = gl.GetError(); if err != gl::NO_ERROR { panic!("GL Error! {:?}", err); } }); } } const VERTEX_SHADER_SRC: &'static [u8] = br#" #version 140 in vec2 a_pos; in vec3 a_color; out vec3 v_color; void main() { v_color = a_color; gl_Position = vec4(a_pos, 0.0, 1.0); } "#; const FRAGMENT_SHADER_SRC: &'static [u8] = br#" #version 140 in vec3 v_color; out vec4 pixcolor; void main() { pixcolor = vec4(v_color, 1.0); } "#;