Mercurial > touhou
comparison examples/anmrenderer.rs @ 705:ed65f9412bc0
anmrenderer: split common loading functions in another module.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Fri, 23 Aug 2019 19:29:00 +0200 |
parents | 84af5bedbde4 |
children | bca515da9047 |
comparison
equal
deleted
inserted
replaced
704:84af5bedbde4 | 705:ed65f9412bc0 |
---|---|
1 use image::{GenericImageView, DynamicImage}; | |
2 use luminance::blending::{Equation, Factor}; | 1 use luminance::blending::{Equation, Factor}; |
3 use luminance::context::GraphicsContext; | 2 use luminance::context::GraphicsContext; |
4 use luminance::framebuffer::Framebuffer; | 3 use luminance::framebuffer::Framebuffer; |
5 use luminance::pipeline::BoundTexture; | 4 use luminance::pipeline::BoundTexture; |
6 use luminance::pixel::{NormRGB8UI, NormRGBA8UI, Floating}; | 5 use luminance::pixel::Floating; |
7 use luminance::render_state::RenderState; | 6 use luminance::render_state::RenderState; |
8 use luminance::shader::program::{Program, Uniform}; | 7 use luminance::shader::program::{Program, Uniform}; |
9 use luminance::tess::{Mode, TessBuilder}; | 8 use luminance::tess::{Mode, TessBuilder}; |
10 use luminance::texture::{Dim2, Flat, Sampler, Texture, GenMipmaps}; | 9 use luminance::texture::{Dim2, Flat}; |
11 use luminance_derive::{Semantics, Vertex, UniformInterface}; | 10 use luminance_derive::{Semantics, Vertex, UniformInterface}; |
12 use luminance_glfw::event::{Action, Key, WindowEvent}; | 11 use luminance_glfw::event::{Action, Key, WindowEvent}; |
13 use luminance_glfw::surface::{GlfwSurface, Surface, WindowDim, WindowOpt}; | 12 use luminance_glfw::surface::{GlfwSurface, Surface, WindowDim, WindowOpt}; |
14 use touhou::th06::anm0::Anm0; | 13 use touhou::th06::anm0::Anm0; |
15 use touhou::th06::anm0_vm::{AnmRunner, Sprite, Vertex as FakeVertex}; | 14 use touhou::th06::anm0_vm::{AnmRunner, Sprite, Vertex as FakeVertex}; |
16 use touhou::util::math::{perspective, setup_camera}; | 15 use touhou::util::math::{perspective, setup_camera}; |
17 use touhou::util::prng::Prng; | 16 use touhou::util::prng::Prng; |
18 use std::cell::RefCell; | 17 use std::cell::RefCell; |
19 use std::fs::File; | |
20 use std::io::{BufReader, Read}; | |
21 use std::rc::Rc; | 18 use std::rc::Rc; |
22 use std::env; | 19 use std::env; |
23 use std::path::Path; | 20 use std::path::Path; |
21 | |
22 #[path = "common.rs"] | |
23 mod common; | |
24 | |
25 use common::{load_file_into_vec, load_rgb_png, load_rgb_a_pngs, LoadedTexture}; | |
24 | 26 |
25 const VS: &str = r#" | 27 const VS: &str = r#" |
26 in ivec3 in_position; | 28 in ivec3 in_position; |
27 in vec2 in_texcoord; | 29 in vec2 in_texcoord; |
28 in vec4 in_color; | 30 in vec4 in_color; |
85 | 87 |
86 #[uniform(name = "mvp")] | 88 #[uniform(name = "mvp")] |
87 mvp: Uniform<[[f32; 4]; 4]>, | 89 mvp: Uniform<[[f32; 4]; 4]>, |
88 } | 90 } |
89 | 91 |
90 fn load_file_into_vec(filename: &Path) -> Vec<u8> { | 92 fn fill_vertices_ptr(sprite: Rc<RefCell<Sprite>>, vertices: *mut Vertex) { |
91 let file = File::open(filename).unwrap(); | 93 let mut fake_vertices = unsafe { std::mem::transmute::<*mut Vertex, &mut [FakeVertex; 4]>(vertices) }; |
92 let mut file = BufReader::new(file); | 94 sprite.borrow().fill_vertices(&mut fake_vertices, 0., 0., 0.); |
93 let mut buf = vec![]; | 95 } |
94 file.read_to_end(&mut buf).unwrap(); | 96 |
95 buf | 97 fn fill_vertices(sprite: Rc<RefCell<Sprite>>, vertices: &mut [Vertex; 4]) { |
96 } | 98 let mut fake_vertices = unsafe { std::mem::transmute::<&mut [Vertex; 4], &mut [FakeVertex; 4]>(vertices) }; |
97 | 99 sprite.borrow().fill_vertices(&mut fake_vertices, 0., 0., 0.); |
98 enum LoadedTexture { | |
99 Rgba(Texture<Flat, Dim2, NormRGBA8UI>), | |
100 Rgb(Texture<Flat, Dim2, NormRGB8UI>), | |
101 } | 100 } |
102 | 101 |
103 fn main() { | 102 fn main() { |
104 // Parse arguments. | 103 // Parse arguments. |
105 let args: Vec<_> = env::args().collect(); | 104 let args: Vec<_> = env::args().collect(); |
138 // Open the image atlas matching this ANM. | 137 // Open the image atlas matching this ANM. |
139 let png_filename = anm_filename.with_file_name(Path::new(&anm0.png_filename).file_name().unwrap()); | 138 let png_filename = anm_filename.with_file_name(Path::new(&anm0.png_filename).file_name().unwrap()); |
140 let tex = match anm0.alpha_filename { | 139 let tex = match anm0.alpha_filename { |
141 Some(ref filename) => { | 140 Some(ref filename) => { |
142 let alpha_filename = anm_filename.with_file_name(Path::new(filename).file_name().unwrap()); | 141 let alpha_filename = anm_filename.with_file_name(Path::new(filename).file_name().unwrap()); |
143 LoadedTexture::Rgba(png_alpha(&mut surface, &png_filename, &alpha_filename).expect("texture loading")) | 142 load_rgb_a_pngs(&mut surface, &png_filename, &alpha_filename).expect("texture loading") |
144 }, | 143 }, |
145 None => { | 144 None => { |
146 LoadedTexture::Rgb(load_from_disk(&mut surface, &png_filename).expect("texture loading")) | 145 load_rgb_png(&mut surface, &png_filename).expect("texture loading") |
147 } | 146 } |
148 }; | 147 }; |
149 | 148 |
150 // set the uniform interface to our type so that we can read textures from the shader | 149 // set the uniform interface to our type so that we can read textures from the shader |
151 let (program, _) = | 150 let (program, _) = |
216 }); | 215 }); |
217 | 216 |
218 surface.swap_buffers(); | 217 surface.swap_buffers(); |
219 } | 218 } |
220 } | 219 } |
221 | |
222 fn fill_vertices_ptr(sprite: Rc<RefCell<Sprite>>, vertices: *mut Vertex) { | |
223 let mut fake_vertices = unsafe { std::mem::transmute::<*mut Vertex, &mut [FakeVertex; 4]>(vertices) }; | |
224 sprite.borrow().fill_vertices(&mut fake_vertices, 0., 0., 0.); | |
225 } | |
226 | |
227 fn fill_vertices(sprite: Rc<RefCell<Sprite>>, vertices: &mut [Vertex; 4]) { | |
228 let mut fake_vertices = unsafe { std::mem::transmute::<&mut [Vertex; 4], &mut [FakeVertex; 4]>(vertices) }; | |
229 sprite.borrow().fill_vertices(&mut fake_vertices, 0., 0., 0.); | |
230 } | |
231 | |
232 fn load_from_disk(surface: &mut GlfwSurface, path: &Path) -> Option<Texture<Flat, Dim2, NormRGB8UI>> { | |
233 // load the texture into memory as a whole bloc (i.e. no streaming) | |
234 match image::open(&path) { | |
235 Ok(img) => { | |
236 let (width, height) = img.dimensions(); | |
237 let texels = img | |
238 .pixels() | |
239 .map(|(_x, _y, rgb)| (rgb[0], rgb[1], rgb[2])) | |
240 .collect::<Vec<_>>(); | |
241 | |
242 // create the luminance texture; the third argument is the number of mipmaps we want (leave it | |
243 // to 0 for now) and the latest is a the sampler to use when sampling the texels in the | |
244 // shader (we’ll just use the default one) | |
245 let tex = | |
246 Texture::new(surface, [width, height], 0, &Sampler::default()).expect("luminance texture creation"); | |
247 | |
248 // the first argument disables mipmap generation (we don’t care so far) | |
249 tex.upload(GenMipmaps::No, &texels); | |
250 | |
251 Some(tex) | |
252 } | |
253 | |
254 Err(e) => { | |
255 eprintln!("cannot open image {}: {}", path.display(), e); | |
256 None | |
257 } | |
258 } | |
259 } | |
260 | |
261 fn png_alpha(surface: &mut GlfwSurface, rgb: &Path, alpha: &Path) -> Option<Texture<Flat, Dim2, NormRGBA8UI>> { | |
262 // load the texture into memory as a whole bloc (i.e. no streaming) | |
263 match image::open(&alpha) { | |
264 Ok(img) => { | |
265 let (width, height) = img.dimensions(); | |
266 let alpha = match img.grayscale() { | |
267 DynamicImage::ImageLuma8(img) => img, | |
268 _ => { | |
269 eprintln!("cannot convert alpha image {} to grayscale", alpha.display()); | |
270 return None; | |
271 } | |
272 }; | |
273 let img = match image::open(&rgb) { | |
274 Ok(img) => img, | |
275 Err(e) => { | |
276 eprintln!("cannot open rgb image {}: {}", rgb.display(), e); | |
277 return None; | |
278 }, | |
279 }; | |
280 let texels = img | |
281 .pixels() | |
282 .zip(alpha.pixels()) | |
283 .map(|((_x, _y, rgb), luma)| (rgb[0], rgb[1], rgb[1], luma[0])) | |
284 .collect::<Vec<_>>(); | |
285 | |
286 // create the luminance texture; the third argument is the number of mipmaps we want (leave it | |
287 // to 0 for now) and the latest is a the sampler to use when sampling the texels in the | |
288 // shader (we’ll just use the default one) | |
289 let tex = | |
290 Texture::new(surface, [width, height], 0, &Sampler::default()).expect("luminance texture creation"); | |
291 | |
292 // the first argument disables mipmap generation (we don’t care so far) | |
293 tex.upload(GenMipmaps::No, &texels); | |
294 | |
295 Some(tex) | |
296 } | |
297 | |
298 Err(e) => { | |
299 eprintln!("cannot open alpha image {}: {}", alpha.display(), e); | |
300 None | |
301 } | |
302 } | |
303 } |