use gfx::format::{Depth, Rgba8}; use gfx::handle::{DepthStencilView, RenderTargetView}; use gfx::state::{CullFace, FrontFace, RasterMethod, Rasterizer}; use gfx::traits::FactoryExt; use gfx::{CommandBuffer, Device, Encoder, Factory, PipelineState, Primitive, Resources}; use gfx_device_gl; use gfx_window_glutin; use glutin::GlWindow; use plexus::buffer::MeshBuffer3; use crate::pipeline::{self, Data, Meta, Transform, Vertex}; const CLEAR_COLOR: [f32; 4] = [0.0, 0.0, 0.0, 1.0]; pub trait SwapBuffers { fn swap_buffers(&mut self) -> Result<(), ()>; } impl SwapBuffers for GlWindow { fn swap_buffers(&mut self) -> Result<(), ()> { match GlWindow::swap_buffers(self) { Ok(_) => Ok(()), Err(_) => Err(()), } } } pub trait UpdateFrameBufferView where R: Resources, { fn update_frame_buffer_view( &self, color: &mut RenderTargetView, depth: &mut DepthStencilView, ); } impl UpdateFrameBufferView for GlWindow { fn update_frame_buffer_view( &self, color: &mut RenderTargetView, depth: &mut DepthStencilView, ) { gfx_window_glutin::update_views(self, color, depth); } } pub trait MetaRenderer { type Window: SwapBuffers + UpdateFrameBufferView; type Resources: Resources; type Factory: Factory; type CommandBuffer: CommandBuffer; type Device: Device; } pub struct GlutinRenderer {} impl MetaRenderer for GlutinRenderer { type Window = GlWindow; type Resources = gfx_device_gl::Resources; type Factory = gfx_device_gl::Factory; type CommandBuffer = gfx_device_gl::CommandBuffer; type Device = gfx_device_gl::Device; } pub struct Renderer where R: MetaRenderer, { pub window: R::Window, pub factory: R::Factory, device: R::Device, encoder: Encoder, state: PipelineState, data: Data, } impl Renderer { pub fn from_glutin_window(window: GlWindow) -> Self { let (device, mut factory, color, depth) = gfx_window_glutin::init_existing(&window); let encoder = factory.create_command_buffer().into(); Renderer::new(window, factory, device, encoder, color, depth) } } impl Renderer where R: MetaRenderer, { fn new( window: R::Window, mut factory: R::Factory, device: R::Device, encoder: Encoder, color: RenderTargetView, depth: DepthStencilView, ) -> Self { let shaders = factory .create_shader_set( include_bytes!("shader.v.glsl"), include_bytes!("shader.f.glsl"), ) .unwrap(); let state = factory .create_pipeline_state( &shaders, Primitive::TriangleList, Rasterizer { method: RasterMethod::Fill, front_face: FrontFace::CounterClockwise, cull_face: CullFace::Back, offset: None, samples: None, }, pipeline::new(), ) .unwrap(); let data = Data { buffer: factory.create_vertex_buffer(&[]), transform: factory.create_constant_buffer(1), camera: [[0.0; 4]; 4], model: [[0.0; 4]; 4], color: color, depth: depth, }; Renderer { window: window, factory: factory, device: device, encoder: encoder, state: state, data: data, } } pub fn set_transform(&mut self, transform: &Transform) -> Result<(), ()> { self.data.camera = transform.camera; self.data.model = transform.model; match self .encoder .update_buffer(&self.data.transform, &[*transform], 0) { Ok(_) => Ok(()), Err(_) => Err(()), } } pub fn draw_mesh_buffer(&mut self, buffer: &MeshBuffer3) { let (buffer, slice) = self .factory .create_vertex_buffer_with_slice(buffer.as_vertex_slice(), buffer.as_index_slice()); self.data.buffer = buffer; self.encoder.draw(&slice, &self.state, &self.data); } pub fn clear(&mut self) { self.encoder.clear(&self.data.color, CLEAR_COLOR); self.encoder.clear_depth(&self.data.depth, 1.0); } pub fn flush(&mut self) -> Result<(), ()> { self.encoder.flush(&mut self.device); match self.window.swap_buffers().and_then(|_| { self.device.cleanup(); Ok(()) }) { Ok(_) => Ok(()), Err(_) => Err(()), } } pub fn update_frame_buffer_view(&mut self) { self.window .update_frame_buffer_view(&mut self.data.color, &mut self.data.depth); } }