From dacee68d89cf0c682d6b0eea57db65113405d81a Mon Sep 17 00:00:00 2001 From: Jared Roberts Date: Tue, 6 Sep 2016 17:15:55 -0700 Subject: [PATCH] pixels from headset --- Cargo.toml | 9 +++ src/bin/gl.rs | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 src/bin/gl.rs diff --git a/Cargo.toml b/Cargo.toml index 2865d96..e00c0be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,17 @@ version = "0.1.0" authors = ["Jared Roberts "] [dependencies] +env_logger = "0.3" itertools = ">=0.4" +log = "0.3" memmap = "~0.2" +gl = "*" +gfx = "*" +gfx_device_gl = "*" +openvr = { git = "https://github.com/rust-openvr/rust-openvr" } +piston = "*" +piston_window = "*" + sdl2 = "0.22" sdl2_image = "0.22" diff --git a/src/bin/gl.rs b/src/bin/gl.rs new file mode 100644 index 0000000..11e048e --- /dev/null +++ b/src/bin/gl.rs @@ -0,0 +1,210 @@ +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); + } +"#;