pub mod camera; use glium::draw_parameters::DepthTest; use glium::texture::{ RawImage2d, SrgbTexture2d, }; use glium::index::{ NoIndices, PrimitiveType }; use glium::{ Program, Display, VertexBuffer, Frame, DrawParameters, Depth, }; use image; use model::{Model, Vertex}; use renderer::camera::Camera; pub struct RenderMaterial { texture: Option, } impl RenderMaterial { pub fn new() -> RenderMaterial { RenderMaterial { texture: None } } pub fn from_texture_name(path: &str, display: &Display) -> RenderMaterial { let image = image::open(path); if let Ok(image) = image { let image = image.to_rgba(); let dim = image.dimensions(); let image = RawImage2d::from_raw_rgba_reversed(&image.into_raw(), dim); RenderMaterial { texture: SrgbTexture2d::new(display, image).ok() } } else { RenderMaterial { texture: None } } } } pub struct Renderer<'a> { display: Display, program: Program, models: Vec<(&'a Model, Vec<(RenderMaterial, VertexBuffer)>)>, } impl<'a> Renderer<'a> { pub fn new(display: Display) -> Renderer<'a> { let program = Program::from_source( &display, include_str!("../../assets/shaders/shader.vert"), include_str!("../../assets/shaders/shader.frag"), None ).unwrap(); Renderer { display: display, program: program, models: vec![], } } pub fn add_model(&mut self, model: &'a Model) { let mut buffers = vec![]; for part in &model.parts { let material = if let Some(ref material_name) = part.material_name { if let Some(material) = model.materials.get(material_name) { if let Some(path) = material.textures.get("map_Kd") { RenderMaterial::from_texture_name(path, &self.display) } else { RenderMaterial::new() } } else { RenderMaterial::new() } } else { RenderMaterial::new() }; let shape = part.build_shape(&model.vertices, &model.texture_coordinates, &model.normals); buffers.push((material, VertexBuffer::new(&self.display, &shape).unwrap())); } self.models.push((model, buffers)); } pub fn draw(&self) -> Frame { self.display.draw() } pub fn render(&self, camera: &C, target: &mut Frame) { use glium::Surface; target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0); let params = DrawParameters { depth: Depth { test: DepthTest::IfLess, write: true, .. Default::default() }, .. Default::default() }; for &(_, ref buffers) in &self.models { for &(ref material, ref buffer) in buffers { let perspective = camera.get_perspective_matrix(target.get_dimensions()); let view = camera.get_view_matrix(); if let &Some(ref texture) = &material.texture { target.draw( buffer, NoIndices(PrimitiveType::TrianglesList), &self.program, &uniform!( tex: texture, perspective: perspective, view: view, ), ¶ms, ).unwrap(); } else { target.draw( buffer, NoIndices(PrimitiveType::TrianglesList), &self.program, &uniform!( perspective: perspective, view: view, ), ¶ms, ).unwrap(); }; } } } }