changeset 706:bca515da9047

examples: use common module.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 23 Aug 2019 19:46:47 +0200
parents ed65f9412bc0
children 987409d48991
files examples/anmrenderer.rs examples/common.rs examples/eclrenderer.rs examples/stdrenderer.rs
diffstat 4 files changed, 62 insertions(+), 117 deletions(-) [+]
line wrap: on
line diff
--- a/examples/anmrenderer.rs
+++ b/examples/anmrenderer.rs
@@ -21,8 +21,7 @@ use std::path::Path;
 
 #[path = "common.rs"]
 mod common;
-
-use common::{load_file_into_vec, load_rgb_png, load_rgb_a_pngs, LoadedTexture};
+use common::{load_file_into_vec, load_anm_image, LoadedTexture};
 
 const VS: &str = r#"
 in ivec3 in_position;
@@ -135,16 +134,7 @@ fn main() {
     let mut surface = GlfwSurface::new(WindowDim::Windowed(384, 448), "Touhou", WindowOpt::default()).unwrap();
 
     // Open the image atlas matching this ANM.
-    let png_filename = anm_filename.with_file_name(Path::new(&anm0.png_filename).file_name().unwrap());
-    let tex = match anm0.alpha_filename {
-        Some(ref filename) => {
-            let alpha_filename = anm_filename.with_file_name(Path::new(filename).file_name().unwrap());
-            load_rgb_a_pngs(&mut surface, &png_filename, &alpha_filename).expect("texture loading")
-        },
-        None => {
-            load_rgb_png(&mut surface, &png_filename).expect("texture loading")
-        }
-    };
+    let tex = load_anm_image(&mut surface, &anm0, anm_filename);
 
     // set the uniform interface to our type so that we can read textures from the shader
     let (program, _) =
--- a/examples/common.rs
+++ b/examples/common.rs
@@ -2,6 +2,7 @@ use image::{GenericImageView, DynamicIma
 use luminance::pixel::{NormRGB8UI, NormRGBA8UI};
 use luminance::texture::{Dim2, Flat, Sampler, Texture, GenMipmaps};
 use luminance_glfw::surface::GlfwSurface;
+use touhou::th06::anm0::Anm0;
 use std::fs::File;
 use std::io::{BufReader, Read};
 use std::path::Path;
@@ -19,7 +20,7 @@ pub enum LoadedTexture {
     Rgb(Texture<Flat, Dim2, NormRGB8UI>),
 }
 
-pub fn load_rgb_png(surface: &mut GlfwSurface, path: &Path) -> Option<LoadedTexture> {
+fn load_rgb_png(surface: &mut GlfwSurface, path: &Path) -> Option<LoadedTexture> {
     // load the texture into memory as a whole bloc (i.e. no streaming)
     match image::open(&path) {
         Ok(img) => {
@@ -48,7 +49,7 @@ pub fn load_rgb_png(surface: &mut GlfwSu
     }
 }
 
-pub fn load_rgb_a_pngs(surface: &mut GlfwSurface, rgb: &Path, alpha: &Path) -> Option<LoadedTexture> {
+fn load_rgb_a_pngs(surface: &mut GlfwSurface, rgb: &Path, alpha: &Path) -> Option<LoadedTexture> {
     // load the texture into memory as a whole bloc (i.e. no streaming)
     match image::open(&alpha) {
         Ok(img) => {
@@ -70,7 +71,7 @@ pub fn load_rgb_a_pngs(surface: &mut Glf
             let texels = img
                 .pixels()
                 .zip(alpha.pixels())
-                .map(|((_x, _y, rgb), luma)| (rgb[0], rgb[1], rgb[1], luma[0]))
+                .map(|((_x, _y, rgb), luma)| (rgb[0], rgb[1], rgb[2], luma[0]))
                 .collect::<Vec<_>>();
 
             // create the luminance texture; the third argument is the number of mipmaps we want (leave it
@@ -91,3 +92,17 @@ pub fn load_rgb_a_pngs(surface: &mut Glf
         }
     }
 }
+
+pub fn load_anm_image(mut surface: &mut GlfwSurface, anm0: &Anm0, anm_filename: &Path) -> LoadedTexture {
+    let png_filename = anm_filename.with_file_name(Path::new(&anm0.png_filename).file_name().unwrap());
+    match anm0.alpha_filename {
+        Some(ref filename) => {
+            let alpha_filename = anm_filename.with_file_name(Path::new(filename).file_name().unwrap());
+            println!("alpha {:?}", alpha_filename);
+            load_rgb_a_pngs(&mut surface, &png_filename, &alpha_filename).expect("texture loading")
+        },
+        None => {
+            load_rgb_png(&mut surface, &png_filename).expect("texture loading")
+        }
+    }
+}
--- a/examples/eclrenderer.rs
+++ b/examples/eclrenderer.rs
@@ -1,12 +1,12 @@
-use image::GenericImageView;
+use luminance::blending::{Equation, Factor};
 use luminance::context::GraphicsContext;
 use luminance::framebuffer::Framebuffer;
 use luminance::pipeline::BoundTexture;
-use luminance::pixel::{NormRGB8UI, Floating};
+use luminance::pixel::Floating;
 use luminance::render_state::RenderState;
 use luminance::shader::program::{Program, Uniform};
 use luminance::tess::{Mode, TessBuilder};
-use luminance::texture::{Dim2, Flat, Sampler, Texture, GenMipmaps};
+use luminance::texture::{Dim2, Flat};
 use luminance_derive::{Semantics, Vertex, UniformInterface};
 use luminance_glfw::event::{Action, Key, WindowEvent};
 use luminance_glfw::surface::{GlfwSurface, Surface, WindowDim, WindowOpt};
@@ -18,12 +18,14 @@ use touhou::th06::enemy::{Enemy, Game, P
 use touhou::util::math::{perspective, setup_camera};
 use touhou::util::prng::Prng;
 use std::cell::RefCell;
-use std::fs::File;
-use std::io::{BufReader, Read};
 use std::rc::Rc;
 use std::env;
 use std::path::Path;
 
+#[path = "common.rs"]
+mod common;
+use common::{load_file_into_vec, load_anm_image, LoadedTexture};
+
 const VS: &str = r#"
 in ivec3 in_position;
 in vec2 in_texcoord;
@@ -88,26 +90,17 @@ struct ShaderInterface {
     mvp: Uniform<[[f32; 4]; 4]>,
 }
 
-fn load_file_into_vec(filename: &str) -> Vec<u8> {
-    let file = File::open(filename).unwrap();
-    let mut file = BufReader::new(file);
-    let mut buf = vec![];
-    file.read_to_end(&mut buf).unwrap();
-    buf
-}
-
 fn main() {
     // Parse arguments.
     let args: Vec<_> = env::args().collect();
-    if args.len() != 6 {
-        eprintln!("Usage: {} <ECL file> <ANM file> <PNG file> <easy|normal|hard|lunatic> <sub number>", args[0]);
+    if args.len() != 5 {
+        eprintln!("Usage: {} <ECL file> <ANM file> <easy|normal|hard|lunatic> <sub number>", args[0]);
         return;
     }
-    let ecl_filename = &args[1];
-    let anm_filename = &args[2];
-    let png_filename = &args[3];
-    let rank: Rank = args[4].parse().expect("rank");
-    let sub: u16 = args[5].parse().expect("number");
+    let ecl_filename = Path::new(&args[1]);
+    let anm_filename = Path::new(&args[2]);
+    let rank: Rank = args[3].parse().expect("rank");
+    let sub: u16 = args[4].parse().expect("number");
 
     // Open the ECL file.
     let buf = load_file_into_vec(ecl_filename);
@@ -142,7 +135,7 @@ fn main() {
     let mut surface = GlfwSurface::new(WindowDim::Windowed(384, 448), "Touhou", WindowOpt::default()).unwrap();
 
     // Open the image atlas matching this ANM.
-    let tex = load_from_disk(&mut surface, Path::new(png_filename)).expect("texture loading");
+    let tex = load_anm_image(&mut surface, &anm0.borrow(), anm_filename);
 
     // set the uniform interface to our type so that we can read textures from the shader
     let (program, _) =
@@ -195,7 +188,10 @@ fn main() {
             .pipeline_builder()
             .pipeline(&back_buffer, [0., 0., 0., 0.], |pipeline, shd_gate| {
                 // bind our fancy texture to the GPU: it gives us a bound texture we can use with the shader
-                let bound_tex = pipeline.bind_texture(&tex);
+                let bound_tex = match &tex {
+                    LoadedTexture::Rgb(tex) => pipeline.bind_texture(tex),
+                    LoadedTexture::Rgba(tex) => pipeline.bind_texture(tex),
+                };
 
                 shd_gate.shade(&program, |rdr_gate, iface| {
                     // update the texture; strictly speaking, this update doesn’t do much: it just tells the GPU
@@ -209,7 +205,10 @@ fn main() {
                     // TODO: check how to pass by reference.
                     iface.mvp.update(*mvp.borrow_inner());
 
-                    rdr_gate.render(RenderState::default(), |tess_gate| {
+                    let render_state = RenderState::default()
+                        .set_blending((Equation::Additive, Factor::SrcAlpha, Factor::SrcAlphaComplement));
+
+                    rdr_gate.render(render_state, |tess_gate| {
                         // render the tessellation to the surface the regular way and let the vertex shader’s
                         // magic do the rest!
                         tess_gate.render(&mut surface, (&tess).into());
@@ -228,32 +227,3 @@ fn fill_vertices_ptr(sprites: Vec<(f32, 
         sprite.fill_vertices(&mut fake_vertices, x, y, z);
     }
 }
-
-fn load_from_disk(surface: &mut GlfwSurface, path: &Path) -> Option<Texture<Flat, Dim2, NormRGB8UI>> {
-    // load the texture into memory as a whole bloc (i.e. no streaming)
-    match image::open(&path) {
-        Ok(img) => {
-            let (width, height) = img.dimensions();
-            let texels = img
-                .pixels()
-                .map(|(x, y, rgb)| (rgb[0], rgb[1], rgb[2]))
-                .collect::<Vec<_>>();
-
-            // create the luminance texture; the third argument is the number of mipmaps we want (leave it
-            // to 0 for now) and the latest is a the sampler to use when sampling the texels in the
-            // shader (we’ll just use the default one)
-            let tex =
-                Texture::new(surface, [width, height], 0, &Sampler::default()).expect("luminance texture creation");
-
-            // the first argument disables mipmap generation (we don’t care so far)
-            tex.upload(GenMipmaps::No, &texels);
-
-            Some(tex)
-        }
-
-        Err(e) => {
-            eprintln!("cannot open image {}: {}", path.display(), e);
-            None
-        }
-    }
-}
--- a/examples/stdrenderer.rs
+++ b/examples/stdrenderer.rs
@@ -1,12 +1,12 @@
-use image::GenericImageView;
+use luminance::blending::{Equation, Factor};
 use luminance::context::GraphicsContext;
 use luminance::framebuffer::Framebuffer;
 use luminance::pipeline::BoundTexture;
-use luminance::pixel::{NormRGB8UI, Floating};
+use luminance::pixel::Floating;
 use luminance::render_state::RenderState;
 use luminance::shader::program::{Program, Uniform};
 use luminance::tess::{Mode, TessBuilder, TessSliceIndex};
-use luminance::texture::{Dim2, Flat, Sampler, Texture, GenMipmaps};
+use luminance::texture::{Dim2, Flat};
 use luminance_derive::{Semantics, Vertex, UniformInterface};
 use luminance_glfw::event::{Action, Key, WindowEvent};
 use luminance_glfw::surface::{GlfwSurface, Surface, WindowDim, WindowOpt};
@@ -17,12 +17,14 @@ use touhou::th06::std_vm::StageRunner;
 use touhou::util::prng::Prng;
 use touhou::util::math::perspective;
 use std::cell::RefCell;
-use std::fs::File;
-use std::io::{BufReader, Read};
 use std::rc::Rc;
 use std::env;
 use std::path::Path;
 
+#[path = "common.rs"]
+mod common;
+use common::{load_file_into_vec, load_anm_image, LoadedTexture};
+
 const VS: &str = r#"
 in ivec3 in_position;
 in vec2 in_texcoord;
@@ -107,24 +109,15 @@ struct ShaderInterface {
     fog_color: Uniform<[f32; 4]>,
 }
 
-fn load_file_into_vec(filename: &str) -> Vec<u8> {
-    let file = File::open(filename).unwrap();
-    let mut file = BufReader::new(file);
-    let mut buf = vec![];
-    file.read_to_end(&mut buf).unwrap();
-    buf
-}
-
 fn main() {
     // Parse arguments.
     let args: Vec<_> = env::args().collect();
-    if args.len() != 4 {
-        eprintln!("Usage: {} <STD file> <ANM file> <PNG file>", args[0]);
+    if args.len() != 3 {
+        eprintln!("Usage: {} <STD file> <ANM file>", args[0]);
         return;
     }
-    let std_filename = &args[1];
-    let anm_filename = &args[2];
-    let png_filename = &args[3];
+    let std_filename = Path::new(&args[1]);
+    let anm_filename = Path::new(&args[2]);
 
     // Open the STD file.
     let buf = load_file_into_vec(std_filename);
@@ -168,7 +161,7 @@ fn main() {
     let mut surface = GlfwSurface::new(WindowDim::Windowed(384, 448), "Touhou", WindowOpt::default()).unwrap();
 
     // Open the image atlas matching this ANM.
-    let tex = load_from_disk(&mut surface, Path::new(png_filename)).expect("texture loading");
+    let tex = load_anm_image(&mut surface, &anm0, anm_filename);
 
     // set the uniform interface to our type so that we can read textures from the shader
     let (program, _) =
@@ -207,7 +200,10 @@ fn main() {
             .pipeline_builder()
             .pipeline(&back_buffer, [0., 0., 0., 0.], |pipeline, shd_gate| {
                 // bind our fancy texture to the GPU: it gives us a bound texture we can use with the shader
-                let bound_tex = pipeline.bind_texture(&tex);
+                let bound_tex = match &tex {
+                    LoadedTexture::Rgb(tex) => pipeline.bind_texture(tex),
+                    LoadedTexture::Rgba(tex) => pipeline.bind_texture(tex),
+                };
 
                 shd_gate.shade(&program, |rdr_gate, iface| {
                     // update the texture; strictly speaking, this update doesn’t do much: it just tells the GPU
@@ -226,11 +222,14 @@ fn main() {
                     iface.fog_scale.update(1. / (far - near));
                     iface.fog_end.update(far);
 
+                    let render_state = RenderState::default()
+                        .set_blending((Equation::Additive, Factor::SrcAlpha, Factor::SrcAlphaComplement));
+
                     let stage = stage_runner.stage.borrow();
                     for instance in stage.instances.iter() {
                         iface.instance_position.update([instance.pos.x, instance.pos.y, instance.pos.z]);
 
-                        rdr_gate.render(RenderState::default(), |tess_gate| {
+                        rdr_gate.render(render_state, |tess_gate| {
                             let (begin, end) = indices[instance.id as usize];
                             tess_gate.render(&mut surface, tess.slice(begin..end));
                         });
@@ -247,32 +246,3 @@ fn fill_vertices(sprite: Rc<RefCell<Spri
     let sprite = sprite.borrow();
     sprite.fill_vertices(&mut fake_vertices, x, y, z);
 }
-
-fn load_from_disk(surface: &mut GlfwSurface, path: &Path) -> Option<Texture<Flat, Dim2, NormRGB8UI>> {
-    // load the texture into memory as a whole bloc (i.e. no streaming)
-    match image::open(&path) {
-        Ok(img) => {
-            let (width, height) = img.dimensions();
-            let texels = img
-                .pixels()
-                .map(|(_x, _y, rgb)| (rgb[0], rgb[1], rgb[2]))
-                .collect::<Vec<_>>();
-
-            // create the luminance texture; the third argument is the number of mipmaps we want (leave it
-            // to 0 for now) and the latest is a the sampler to use when sampling the texels in the
-            // shader (we’ll just use the default one)
-            let tex =
-                Texture::new(surface, [width, height], 0, &Sampler::default()).expect("luminance texture creation");
-
-            // the first argument disables mipmap generation (we don’t care so far)
-            tex.upload(GenMipmaps::No, &texels);
-
-            Some(tex)
-        }
-
-        Err(e) => {
-            eprintln!("cannot open image {}: {}", path.display(), e);
-            None
-        }
-    }
-}