comparison examples/stagerunner.rs @ 753:a662dddd4a2b

examples: Use array textures for enemy PNGs This requires luminance 0.39.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 25 Feb 2020 21:03:44 +0100
parents 5e5e7136ac92
children
comparison
equal deleted inserted replaced
752:5e5e7136ac92 753:a662dddd4a2b
3 use luminance::pipeline::{BoundTexture, PipelineState}; 3 use luminance::pipeline::{BoundTexture, PipelineState};
4 use luminance::pixel::NormUnsigned; 4 use luminance::pixel::NormUnsigned;
5 use luminance::render_state::RenderState; 5 use luminance::render_state::RenderState;
6 use luminance::shader::program::{Program, Uniform}; 6 use luminance::shader::program::{Program, Uniform};
7 use luminance::tess::{Mode, TessBuilder}; 7 use luminance::tess::{Mode, TessBuilder};
8 use luminance::texture::{Dim2, Flat}; 8 use luminance::texture::Dim2Array;
9 use luminance_derive::{Semantics, Vertex, UniformInterface}; 9 use luminance_derive::{Semantics, Vertex, UniformInterface};
10 use luminance_glfw::{Action, Key, WindowEvent, GlfwSurface, Surface, WindowDim, WindowOpt}; 10 use luminance_glfw::{Action, Key, WindowEvent, GlfwSurface, Surface, WindowDim, WindowOpt};
11 use touhou::th06::anm0::Anm0; 11 use touhou::th06::anm0::Anm0;
12 use touhou::th06::anm0_vm::Vertex as FakeVertex; 12 use touhou::th06::anm0_vm::Vertex as FakeVertex;
13 use touhou::th06::ecl::{Ecl, Rank, MainInstruction}; 13 use touhou::th06::ecl::{Ecl, Rank, MainInstruction};
20 use std::env; 20 use std::env;
21 use std::path::Path; 21 use std::path::Path;
22 22
23 #[path = "common.rs"] 23 #[path = "common.rs"]
24 mod common; 24 mod common;
25 use common::{load_file_into_vec, load_anm_image, LoadedTexture}; 25 use common::{load_file_into_vec, load_multiple_anm_images, LoadedTexture};
26 26
27 const VS: &str = r#" 27 const VS: &str = r#"
28 in ivec3 in_position; 28 in ivec3 in_position;
29 in uint in_layer;
29 in vec2 in_texcoord; 30 in vec2 in_texcoord;
30 in uvec4 in_color; 31 in uvec4 in_color;
31 32
32 uniform mat4 mvp; 33 uniform mat4 mvp;
33 34
35 flat out uint layer;
34 out vec2 texcoord; 36 out vec2 texcoord;
35 out vec4 color; 37 out vec4 color;
36 38
37 void main() 39 void main()
38 { 40 {
39 gl_Position = mvp * vec4(vec3(in_position), 1.0); 41 gl_Position = mvp * vec4(vec3(in_position), 1.0);
40 texcoord = vec2(in_texcoord); 42 texcoord = vec2(in_texcoord);
41 43
42 // Normalized from the u8 being passed. 44 // Normalized from the u8 being passed.
43 color = vec4(in_color) / 255.; 45 color = vec4(in_color) / 255.;
46
47 layer = in_layer;
44 } 48 }
45 "#; 49 "#;
46 50
47 const FS: &str = r#" 51 const FS: &str = r#"
52 flat in uint layer;
48 in vec2 texcoord; 53 in vec2 texcoord;
49 in vec4 color; 54 in vec4 color;
50 55
51 uniform sampler2D color_map; 56 uniform sampler2DArray color_map;
52 57
53 out vec4 frag_color; 58 out vec4 frag_color;
54 59
55 void main() 60 void main()
56 { 61 {
57 frag_color = texture(color_map, texcoord) * color; 62 frag_color = texture(color_map, vec3(texcoord, layer)) * color;
58 } 63 }
59 "#; 64 "#;
60 65
61 #[derive(Clone, Copy, Debug, Eq, PartialEq, Semantics)] 66 #[derive(Clone, Copy, Debug, Eq, PartialEq, Semantics)]
62 pub enum Semantics { 67 pub enum Semantics {
63 #[sem(name = "in_position", repr = "[i16; 3]", wrapper = "VertexPosition")] 68 #[sem(name = "in_position", repr = "[i16; 3]", wrapper = "VertexPosition")]
64 Position, 69 Position,
70
71 #[sem(name = "in_layer", repr = "u16", wrapper = "VertexLayer")]
72 Layer,
65 73
66 #[sem(name = "in_texcoord", repr = "[f32; 2]", wrapper = "VertexTexcoord")] 74 #[sem(name = "in_texcoord", repr = "[f32; 2]", wrapper = "VertexTexcoord")]
67 Texcoord, 75 Texcoord,
68 76
69 #[sem(name = "in_color", repr = "[u8; 4]", wrapper = "VertexColor")] 77 #[sem(name = "in_color", repr = "[u8; 4]", wrapper = "VertexColor")]
73 #[repr(C)] 81 #[repr(C)]
74 #[derive(Clone, Copy, Debug, PartialEq, Vertex)] 82 #[derive(Clone, Copy, Debug, PartialEq, Vertex)]
75 #[vertex(sem = "Semantics")] 83 #[vertex(sem = "Semantics")]
76 struct Vertex { 84 struct Vertex {
77 pos: VertexPosition, 85 pos: VertexPosition,
86 layer: VertexLayer,
78 uv: VertexTexcoord, 87 uv: VertexTexcoord,
79 rgba: VertexColor, 88 rgba: VertexColor,
80 } 89 }
81 90
82 #[derive(UniformInterface)] 91 #[derive(UniformInterface)]
83 struct ShaderInterface { 92 struct ShaderInterface {
84 // the 'static lifetime acts as “anything” here 93 // the 'static lifetime acts as “anything” here
85 color_map: Uniform<&'static BoundTexture<'static, Flat, Dim2, NormUnsigned>>, 94 color_map: Uniform<&'static BoundTexture<'static, Dim2Array, NormUnsigned>>,
86 95
87 #[uniform(name = "mvp")] 96 #[uniform(name = "mvp")]
88 mvp: Uniform<[[f32; 4]; 4]>, 97 mvp: Uniform<[[f32; 4]; 4]>,
89 } 98 }
90 99
134 }; 143 };
135 144
136 let mut surface = GlfwSurface::new(WindowDim::Windowed(384, 448), "Touhou", WindowOpt::default()).unwrap(); 145 let mut surface = GlfwSurface::new(WindowDim::Windowed(384, 448), "Touhou", WindowOpt::default()).unwrap();
137 146
138 // Open the image atlas matching this ANM. 147 // Open the image atlas matching this ANM.
139 let mut textures = vec![]; 148 let tex = load_multiple_anm_images(&mut surface, &anms, &anm_filename).expect("image loading");
140 for anm0 in anms.iter() {
141 let tex = load_anm_image(&mut surface, &anm0, &anm_filename).expect("image loading");
142 textures.push(tex);
143 }
144
145 let anms = Rc::new(RefCell::new(anms)); 149 let anms = Rc::new(RefCell::new(anms));
146 let tex = textures.pop().unwrap();
147 let tex = textures.pop().unwrap();
148 150
149 // set the uniform interface to our type so that we can read textures from the shader 151 // set the uniform interface to our type so that we can read textures from the shader
150 let program = 152 let program =
151 Program::<Semantics, (), ShaderInterface>::from_strings(None, VS, None, FS).expect("program creation").ignore_warnings(); 153 Program::<Semantics, (), ShaderInterface>::from_strings(None, VS, None, FS).expect("program creation").ignore_warnings();
152 154
207 surface 209 surface
208 .pipeline_builder() 210 .pipeline_builder()
209 .pipeline(&back_buffer, &PipelineState::default(), |pipeline, mut shd_gate| { 211 .pipeline(&back_buffer, &PipelineState::default(), |pipeline, mut shd_gate| {
210 // bind our fancy texture to the GPU: it gives us a bound texture we can use with the shader 212 // bind our fancy texture to the GPU: it gives us a bound texture we can use with the shader
211 let bound_tex = match &tex { 213 let bound_tex = match &tex {
212 LoadedTexture::Rgb(tex) => pipeline.bind_texture(tex), 214 LoadedTexture::Rgb(tex) => unreachable!(),
213 LoadedTexture::Rgba(tex) => pipeline.bind_texture(tex), 215 LoadedTexture::Rgba(tex) => unreachable!(),
216 LoadedTexture::RgbaArray(tex) => pipeline.bind_texture(tex),
214 }; 217 };
215 218
216 shd_gate.shade(&program, |iface, mut rdr_gate| { 219 shd_gate.shade(&program, |iface, mut rdr_gate| {
217 // update the texture; strictly speaking, this update doesn’t do much: it just tells the GPU 220 // update the texture; strictly speaking, this update doesn’t do much: it just tells the GPU
218 // to use the texture passed as argument (no allocation or copy is performed) 221 // to use the texture passed as argument (no allocation or copy is performed)
224 //println!("{:#?}", mvp); 227 //println!("{:#?}", mvp);
225 // TODO: check how to pass by reference. 228 // TODO: check how to pass by reference.
226 iface.mvp.update(*mvp.borrow_inner()); 229 iface.mvp.update(*mvp.borrow_inner());
227 230
228 let render_state = RenderState::default() 231 let render_state = RenderState::default()
232 .set_depth_test(None)
229 .set_blending((Equation::Additive, Factor::SrcAlpha, Factor::SrcAlphaComplement)); 233 .set_blending((Equation::Additive, Factor::SrcAlpha, Factor::SrcAlphaComplement));
230 234
231 rdr_gate.render(&render_state, |mut tess_gate| { 235 rdr_gate.render(&render_state, |mut tess_gate| {
232 let mut game = game.borrow_mut(); 236 let mut game = game.borrow_mut();
233 game.run_frame(); 237 game.run_frame();