model-converter/src/renderer.rs

159 lines
4.8 KiB
Rust
Raw Normal View History

2018-04-17 10:45:44 +02:00
//! This module contains the rendering structs.
use std::cell::Ref;
use image;
use glium::texture::{RawImage2d, SrgbTexture2d};
use glium::{Frame, Display, Surface, Program, DrawParameters, Depth, VertexBuffer};
use glium::draw_parameters::{DepthTest, Blend};
use glium::index::{NoIndices, PrimitiveType};
use glium::glutin::GlWindow;
use scene::Scene;
use camera::RenderCamera;
use model::{Vertex, Part, Model};
/// A renderer. It contains a display, shaders, and some rendering parameters.
pub struct Renderer {
/// The display on which the rendering will be done.
display: Display,
/// The shading program.
program: Program,
/// The background color.
clear_color: (f32, f32, f32, f32),
}
impl Renderer {
/// Creates a new renderer from a display.
///
/// Is uses the default shaders and creates an empty vec of models.
pub fn new(display: Display) -> Renderer {
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,
clear_color: (0.0, 0.0, 0.0, 1.0),
}
}
/// Returns the inner GlWindows.
pub fn gl_window(&self) -> Ref<GlWindow> {
self.display.gl_window()
}
/// Creates a SrgbTexture from a path to an image.
pub fn make_texture(&self, path: &str) -> SrgbTexture2d {
let image = image::open(path).unwrap().to_rgba();
let dimensions = image.dimensions();
let image = RawImage2d::from_raw_rgba_reversed(&image.into_raw(), dimensions);
SrgbTexture2d::new(&self.display, image).ok().unwrap()
}
/// Creates a frame from the display.
pub fn draw(&self) -> Frame {
self.display.draw()
}
/// Renders on the display.
pub fn render<C: RenderCamera>(&self, scene: &Scene, camera: &C) {
let mut target = self.draw();
target.clear_color_and_depth(self.clear_color, 1.0);
let perspective = camera.get_perspective_matrix();
let view = camera.get_view_matrix();
let params = DrawParameters {
depth: Depth {
test: DepthTest::IfLess,
write: true,
.. Default::default()
},
blend: Blend::alpha_blending(),
.. Default::default()
};
for model in scene.iter() {
let model = &*model.borrow();
for part in &model.parts {
if let &Some(ref buffer) = part.vertex_buffer() {
let texture = self.get_texture_of_part(&model, part);
if let Some(texture) = texture {
target.draw(
buffer,
NoIndices(PrimitiveType::TrianglesList),
&self.program,
&uniform!(
tex: texture,
perspective: perspective,
view: view,
),
&params,
).unwrap();
} else {
target.draw(
buffer,
NoIndices(PrimitiveType::TrianglesList),
&self.program,
&uniform!(
perspective: perspective,
view: view,
),
&params,
).unwrap();
}
}
}
}
target.finish().unwrap();
}
/// Renders a part of a model.
fn get_texture_of_part<'a>(&self, model: &'a Model, part: &Part) -> Option<&'a SrgbTexture2d> {
if let Some(ref material_name) = part.material_name {
if let Some(ref material) = model.materials.get(material_name) {
if let Some(ref texture) = material.rendering_texture {
Some(texture)
} else {
None
}
} else {
None
}
} else {
None
}
}
/// Builds a vertex buffer from a vector of vertex.
pub fn build_vertex_buffer(&self, vertices: &Vec<Vertex>) -> VertexBuffer<Vertex> {
VertexBuffer::new(&self.display, vertices).unwrap()
}
/// Changes the clear color of the renderer.
pub fn set_clear_color(&mut self, r: f32, g: f32, b: f32, a: f32) {
self.clear_color = (r, g, b, a);
}
/// Shows the window if hidden.
pub fn show(&mut self) {
self.gl_window().show();
}
}