Mercurial > touhou
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(); |