Refactored drawing code a little bit
Getty Ritter
9 years ago
| 1 | #version 140 | |
| 2 | ||
| 3 | in vec3 o_nrm; | |
| 4 | in vec2 o_tex; | |
| 5 | ||
| 6 | uniform vec3 u_light; | |
| 7 | uniform sampler2D tex; | |
| 8 | ||
| 9 | out vec4 color; | |
| 10 | ||
| 11 | void main() { | |
| 12 | float brightness = dot(normalize(o_nrm), normalize(u_light)); | |
| 13 | float factor = 0.5 + (brightness * 0.5); | |
| 14 | color = texture(tex, o_tex) * factor; | |
| 15 | } |
| 1 | #version 140 | |
| 2 | ||
| 3 | in vec3 pos; | |
| 4 | in vec3 nrm; | |
| 5 | in vec2 tex; | |
| 6 | ||
| 7 | uniform mat4 perspective; | |
| 8 | uniform mat4 matrix; | |
| 9 | ||
| 10 | out vec3 o_nrm; | |
| 11 | out vec2 o_tex; | |
| 12 | ||
| 13 | void main() { | |
| 14 | o_nrm = transpose(inverse(mat3(matrix))) * nrm; | |
| 15 | o_tex = tex; | |
| 16 | gl_Position = perspective * matrix * vec4(pos, 1.0); | |
| 17 | } |
| 1 | 1 | extern crate glium; |
| 2 | 2 | |
| 3 | use glium::{DisplayBuild, Display, Frame, Surface}; | |
| 4 | use glium::glutin::WindowBuilder; | |
| 3 | use glium::{DisplayBuild, Display, Frame, Program, Surface}; | |
| 4 | use glium::glutin::{Event,WindowBuilder}; | |
| 5 | use glium::texture::{RawImage2d,Texture2d}; | |
| 5 | 6 | |
| 6 | struct Graphics { | |
| 7 | use model::Model; | |
| 8 | ||
| 9 | const VERTEX_SHADER: &'static str = include_str!("../data/shaders/vertex.glsl"); | |
| 10 | ||
| 11 | const FRAGMENT_SHADER: &'static str = include_str!("../data/shaders/fragment.glsl"); | |
| 12 | ||
| 13 | pub struct Graphics { | |
| 7 | 14 | disp: Display, |
| 15 | rt: f32, | |
| 16 | px: f32, | |
| 17 | py: f32, | |
| 18 | pz: f32, | |
| 19 | light: [f32;3], | |
| 20 | model: Model, | |
| 21 | program: Program, | |
| 22 | tex: Texture2d, | |
| 8 | 23 | } |
| 9 | 24 | |
| 10 | 25 | impl Graphics { |
| 11 |
|
|
| 26 | pub fn new(m: Model, t: RawImage2d<u8>) -> Self { | |
| 12 | 27 | let disp = WindowBuilder::new() |
| 13 | 28 | .with_title(format!("utmyen")) |
| 14 | 29 | .with_depth_buffer(24) |
| 15 | 30 | .build_glium() |
| 16 | 31 | .unwrap(); |
| 17 |
|
|
| 32 | let program = Program::from_source( | |
| 33 | &disp, | |
| 34 | VERTEX_SHADER, | |
| 35 | FRAGMENT_SHADER, | |
| 36 | None).unwrap(); | |
| 37 | let tex = Texture2d::new(&disp, t).unwrap(); | |
| 38 | Graphics { | |
| 39 | disp: disp, | |
| 40 | rt: 0.0, | |
| 41 | px: 0.0, | |
| 42 | py: 0.0, | |
| 43 | pz: 0.0, | |
| 44 | light: [-1.0, 0.4, 0.9f32], | |
| 45 | model: m, | |
| 46 | program: program, | |
| 47 | tex: tex, | |
| 48 | } | |
| 18 | 49 | } |
| 19 | 50 | |
| 20 | fn run(&mut self) { | |
| 21 | while (Target { frame: self.disp.draw() }).step() {} | |
| 51 | pub fn run(&mut self) { | |
| 52 | loop { | |
| 53 | let mut tgt = self.disp.draw(); | |
| 54 | if ! (Target { frame: &mut tgt }).step(self) { | |
| 55 | return; | |
| 56 | } | |
| 57 | tgt.finish().unwrap(); | |
| 58 | ||
| 59 | for ev in self.disp.poll_events() { | |
| 60 | match ev { | |
| 61 | Event::Closed => return, | |
| 62 | Event::KeyboardInput(_, n, _) => | |
| 63 | match n { | |
| 64 | 9 => return, | |
| 65 | 24 => self.rt -= 0.1, | |
| 66 | 25 => self.py -= DX, | |
| 67 | 26 => self.rt += 0.1, | |
| 68 | 38 => self.px -= DX, | |
| 69 | 39 => self.py += DX, | |
| 70 | 40 => self.px += DX, | |
| 71 | 44 => self.pz -= DX, | |
| 72 | 45 => self.pz += DX, | |
| 73 | _ => {}, | |
| 74 | }, | |
| 75 | _ => {}, | |
| 76 | } | |
| 77 | } | |
| 78 | } | |
| 22 | 79 | } |
| 23 | 80 | } |
| 24 | 81 | |
| 25 | struct Target { | |
| 26 | frame: Frame, | |
| 82 | const DX: f32 = 0.001; | |
| 83 | const SX: f32 = 0.01; | |
| 84 | ||
| 85 | struct Target<'a> { | |
| 86 | frame: &'a mut Frame, | |
| 27 | 87 | } |
| 28 | 88 | |
| 29 | impl Target { | |
| 30 | fn step(&mut self) -> bool { | |
| 31 | let light = [-1.0, 0.4, 0.9f32]; | |
| 89 | impl<'a> Target<'a> { | |
| 90 | fn step(&mut self, g: &mut Graphics) -> bool { | |
| 32 | 91 | let uniforms = uniform! { |
| 33 | 92 | perspective: self.perspective(), |
| 34 | u_light: light, | |
| 35 | matrix: self.matrix(), | |
| 93 | u_light: g.light, | |
| 94 | matrix: self.matrix(g), | |
| 95 | tx: &g.tex, | |
| 36 | 96 | }; |
| 37 | 97 | |
| 38 | 98 | let params = glium::DrawParameters { |
| 43 | 103 | }, |
| 44 | 104 | .. Default::default() |
| 45 | 105 | }; |
| 106 | ||
| 107 | let vbuf = g.model.get_vbuf(&g.disp); | |
| 108 | let idxs = g.model.get_ibuf(&g.disp); | |
| 109 | self.frame.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0); | |
| 110 | self.frame.draw(&vbuf, | |
| 111 | &idxs, | |
| 112 | &g.program, | |
| 113 | &uniforms, | |
| 114 | ¶ms).unwrap(); | |
| 46 | 115 | return true; |
| 47 | 116 | } |
| 48 | 117 | |
| 49 | fn matrix(&self) -> [[f32;4];4] { | |
| 50 | let rt = 0.0f32; | |
| 51 | let sx = 0.0f32; | |
| 52 | let px = 0.0f32; | |
| 53 | let py = 0.0f32; | |
| 54 | let pz = 0.0f32; | |
| 55 | [ [ rt.cos() * sx, 0.0, -rt.sin() * sx, 0.0 ], | |
| 56 | [ 0.0, sx, 0.0, 0.0 ], | |
| 57 | [ rt.sin() * sx, 0.0, rt.cos() * sx, 0.0 ], | |
| 58 | [ px, pz, py, sx ] | |
| 118 | fn matrix(&self, g: &Graphics) -> [[f32;4];4] { | |
| 119 | let rt = g.rt; | |
| 120 | let px = g.px; | |
| 121 | let py = g.py; | |
| 122 | let pz = g.pz; | |
| 123 | [ [ rt.cos() * SX, 0.0, -rt.sin() * SX, 0.0 ], | |
| 124 | [ 0.0, SX, 0.0, 0.0 ], | |
| 125 | [ rt.sin() * SX, 0.0, rt.cos() * SX, 0.0 ], | |
| 126 | [ px, pz, py, SX ] | |
| 59 | 127 | ] |
| 60 | 128 | } |
| 61 | 129 | |
| 6 | 6 | mod model; |
| 7 | 7 | mod graphics; |
| 8 | 8 | |
| 9 | use glium::{DisplayBuild, Program, Surface}; | |
| 10 | use glium::glutin::Event; | |
| 11 | use glium::glutin::WindowBuilder; | |
| 12 | use glium::texture::Texture2d; | |
| 9 | use glium::texture::{RawImage2d}; | |
| 13 | 10 | |
| 14 | 11 | fn sample() -> model::Model { |
| 15 | 12 | let file = std::env::args().nth(1) |
| 17 | 14 | model::Model::load_from_file(&file).unwrap() |
| 18 | 15 | } |
| 19 | 16 | |
| 20 |
fn sample_texture |
|
| 17 | fn sample_texture<'a>() -> RawImage2d<'a, u8> { | |
| 21 | 18 | use std::io::Cursor; |
| 22 | let img = image::load(Cursor::new(&include_bytes!("/home/gdritter/pictures/cube-uv.png")[..]), | |
| 23 | image::PNG).unwrap().to_rgba(); | |
| 19 | let img = image::load( | |
| 20 | Cursor::new(&include_bytes!("/home/gdritter/pictures/rainbow.png")[..]), | |
| 21 | image::PNG).unwrap().to_rgba(); | |
| 24 | 22 | let dims = img.dimensions(); |
| 25 | 23 | let img = glium::texture::RawImage2d::from_raw_rgba_reversed(img.into_raw(), dims); |
| 26 |
|
|
| 24 | img | |
| 27 | 25 | } |
| 28 | ||
| 29 | const VERTEX_SHADER: &'static str = r#" | |
| 30 | #version 140 | |
| 31 | ||
| 32 | in vec3 pos; | |
| 33 | in vec3 nrm; | |
| 34 | in vec2 tex; | |
| 35 | ||
| 36 | uniform mat4 perspective; | |
| 37 | uniform mat4 matrix; | |
| 38 | ||
| 39 | out vec3 o_nrm; | |
| 40 | out vec2 o_tex; | |
| 41 | ||
| 42 | void main() { | |
| 43 | o_nrm = transpose(inverse(mat3(matrix))) * nrm; | |
| 44 | o_tex = tex; | |
| 45 | gl_Position = perspective * matrix * vec4(pos, 1.0); | |
| 46 | } | |
| 47 | "#; | |
| 48 | ||
| 49 | const FRAGMENT_SHADER: &'static str = r#" | |
| 50 | #version 140 | |
| 51 | ||
| 52 | in vec3 o_nrm; | |
| 53 | in vec2 o_tex; | |
| 54 | ||
| 55 | uniform vec3 u_light; | |
| 56 | uniform sampler2D tex; | |
| 57 | ||
| 58 | out vec4 color; | |
| 59 | ||
| 60 | void main() { | |
| 61 | float brightness = dot(normalize(o_nrm), normalize(u_light)); | |
| 62 | float factor = 0.5 + (brightness * 0.5); | |
| 63 | color = texture(tex, o_tex) * factor; | |
| 64 | } | |
| 65 | "#; | |
| 66 | 26 | |
| 67 | 27 | fn main() { |
| 68 | 28 | let md = sample(); |
| 69 | let display = WindowBuilder::new() | |
| 70 | .with_title(format!("utymen")) | |
| 71 | .with_depth_buffer(24) | |
| 72 | .build_glium() | |
| 73 |
|
|
| 29 | let tex = sample_texture(); | |
| 74 | 30 | |
| 75 | let vbuf = md.get_vbuf(&display); | |
| 76 | let idxs = md.get_ibuf(&display); | |
| 77 | let tx = md.get_tex(&display).unwrap_or(sample_texture(&display)); | |
| 78 | ||
| 79 | let program = Program::from_source( | |
| 80 | &display, | |
| 81 | VERTEX_SHADER, | |
| 82 | FRAGMENT_SHADER, | |
| 83 | None).unwrap(); | |
| 84 | ||
| 85 | let light = [-1.0, 0.4, 0.9f32]; | |
| 86 | let mut px = 0f32; | |
| 87 | let mut py = 0.02f32; | |
| 88 | let mut pz = 0.0f32; | |
| 89 | let mut rt = 0f32; | |
| 90 | let dx = 0.001; | |
| 91 | let sx = 0.01f32; | |
| 92 | ||
| 93 | loop { | |
| 94 | let mut target = display.draw(); | |
| 95 | ||
| 96 | let perspective = { | |
| 97 | let (width, height) = target.get_dimensions(); | |
| 98 | let aspect_ratio = height as f32 / width as f32; | |
| 99 | ||
| 100 | let fov: f32 = 3.141592 / 3.0; | |
| 101 | let zfar = 1024.0; | |
| 102 | let znear = 0.1; | |
| 103 | ||
| 104 | let f = 1.0 / (fov / 2.0).tan(); | |
| 105 | ||
| 106 | [ | |
| 107 | [f * aspect_ratio , 0.0, 0.0 , 0.0], | |
| 108 | [ 0.0 , f , 0.0 , 0.0], | |
| 109 | [ 0.0 , 0.0, (zfar+znear)/(zfar-znear) , 1.0], | |
| 110 | [ 0.0 , 0.0, -(2.0*zfar*znear)/(zfar-znear), 0.0], | |
| 111 | ] | |
| 112 | }; | |
| 113 | ||
| 114 | let uniforms = uniform! { | |
| 115 | perspective: perspective, | |
| 116 | u_light: light, | |
| 117 | tex: &tx, | |
| 118 | matrix: [ [ rt.cos() * sx, 0.0, -rt.sin() * sx, 0.0 ], | |
| 119 | [ 0.0, sx, 0.0, 0.0 ], | |
| 120 | [ rt.sin() * sx, 0.0, rt.cos() * sx, 0.0 ], | |
| 121 | [ px, pz, py, sx ] | |
| 122 | ] | |
| 123 | }; | |
| 124 | ||
| 125 | let params = glium::DrawParameters { | |
| 126 | depth: glium::Depth { | |
| 127 | test: glium::draw_parameters::DepthTest::IfLess, | |
| 128 | write: true, | |
| 129 | .. Default::default() | |
| 130 | }, | |
| 131 | .. Default::default() | |
| 132 | }; | |
| 133 | ||
| 134 | target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0); | |
| 135 | target.draw(&vbuf, | |
| 136 | &idxs, | |
| 137 | &program, | |
| 138 | &uniforms, | |
| 139 | ¶ms).unwrap(); | |
| 140 | target.finish().unwrap(); | |
| 141 | ||
| 142 | for ev in display.poll_events() { | |
| 143 | match ev { | |
| 144 | Event::Closed => return, | |
| 145 | Event::KeyboardInput(_, n, _) => | |
| 146 | match n { | |
| 147 | 9 => return, | |
| 148 | 24 => rt -= 0.1, | |
| 149 | 25 => py -= dx, | |
| 150 | 26 => rt += 0.1, | |
| 151 | 38 => px -= dx, | |
| 152 | 39 => py += dx, | |
| 153 | 40 => px += dx, | |
| 154 | 44 => pz -= dx, | |
| 155 | 45 => pz += dx, | |
| 156 | _ => {}, | |
| 157 | }, | |
| 158 | _ => {}, | |
| 159 | } | |
| 160 | } | |
| 161 |
|
|
| 31 | let mut g = graphics::Graphics::new(md, tex); | |
| 32 | g.run(); | |
| 162 | 33 | } |