Refactored drawing code a little bit
Getty Ritter
8 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 | } |