159 lines
4.8 KiB
Rust
159 lines
4.8 KiB
Rust
|
//! 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,
|
||
|
),
|
||
|
¶ms,
|
||
|
).unwrap();
|
||
|
} else {
|
||
|
target.draw(
|
||
|
buffer,
|
||
|
NoIndices(PrimitiveType::TrianglesList),
|
||
|
&self.program,
|
||
|
&uniform!(
|
||
|
perspective: perspective,
|
||
|
view: view,
|
||
|
),
|
||
|
¶ms,
|
||
|
).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();
|
||
|
}
|
||
|
}
|