Start using normal map in drawing as well
Getty Ritter
6 years ago
3 | 3 | in vec2 t_uv; |
4 | 4 | out vec4 out_color; |
5 | 5 | |
6 | uniform sampler2D nrm; | |
6 | 7 | uniform sampler2D tex; |
7 | 8 | |
8 | 9 | void main() { |
9 |
|
|
10 | vec4 light_dir = normalize(vec4(1.0, 1.0, 1.0, 1.0)); | |
11 | ||
12 | vec4 pixel = texture(tex, t_uv); | |
13 | vec4 normal = texture(nrm, t_uv); | |
14 | ||
15 | float l = max(dot(light_dir, normalize(normal)), 0.0); | |
16 | vec3 col = vec3(pixel) * pow(l, 4.0); | |
17 | out_color = vec4(col, 1.0); | |
10 | 18 | } |
7 | 7 | |
8 | 8 | use board::coord::{Coord, Pair}; |
9 | 9 | |
10 | const BOARD_WIDTH: u16 = 16; | |
11 | const BOARD_HEIGHT: u16 = 12; | |
12 | const TILE_SIZE: u16 = 24; | |
13 | const HALF_TILE_SIZE: f32 = 24.0; | |
10 | pub const BOARD_WIDTH: u16 = 16; | |
11 | pub const BOARD_HEIGHT: u16 = 12; | |
12 | pub const TILE_SIZE: u16 = 24; | |
13 | pub const HALF_TILE_SIZE: f32 = 24.0; | |
14 | 14 | |
15 | 15 | #[derive(PartialEq, Eq, Debug)] |
16 | 16 | pub struct Tile { |
17 |
|
|
17 | pub sprite: Coord, | |
18 | 18 | } |
19 | 19 | |
20 | 20 | impl Tile { |
76 | 76 | } |
77 | 77 | } |
78 | 78 | |
79 | /// Get the set of entities present at the board location that | |
80 | /// this entity is currently looking at | |
79 | 81 | fn get_focus<'a>(&self, b: &'a Board) -> &'a Vec<Entity> { |
80 | 82 | b.get_entity(self.game_coords()) |
81 | 83 | } |
82 | 84 | |
85 | /// Attempt to move this entity, figuring out whether it can move | |
86 | /// and how far to move if so. This does collision detection based | |
87 | /// on the grid and also does some nudging to push the player | |
88 | /// towards being grid-aligned. | |
83 | 89 | fn mv(&self, b: &Board) -> Delta { |
84 | 90 | if self.dir == Pair::zero() { |
85 | 91 | return Delta::zero(); |
96 | 102 | delta.dy = self.dir.y; |
97 | 103 | } else if self.check_collision(b, Pair { y: 0.0, ..self.dir }) { |
98 | 104 | delta.dx = self.dir.x; |
99 | } else { | |
100 | // zeroes are fine | |
101 | }; | |
102 | ||
105 | } | |
106 | ||
107 | // if we're not aligned along a half-square, we should try to | |
108 | // push towards aligning there! | |
103 | 109 | if self.dir.x.eq(&0.0) && !self.dir.y.eq(&0.0) { |
104 | 110 | let xm = self.loc.x % HALF_TILE_SIZE; |
105 |
if 0.0 < xm && |
|
111 | if 0.0 < xm && | |
112 | xm < HALF_TILE_SIZE && | |
113 | self.check_collision(b, Pair { x: -1.0, y: 0.0 }) { | |
106 | 114 | delta.dx = delta.dx - 1.0; |
107 |
} else if xm >= HALF_TILE_SIZE && |
|
115 | } else if xm >= HALF_TILE_SIZE && | |
116 | self.check_collision(b, Pair { x: 1.0, y: 0.0 }) { | |
108 | 117 | delta.dx = delta.dx + 1.0; |
109 | 118 | } |
110 | 119 | } else if !self.dir.x.eq(&0.0) && self.dir.y.eq(&0.0) { |
119 | 128 | delta |
120 | 129 | } |
121 | 130 | |
131 | /// Get this entity's current location in terms of the game | |
132 | /// coordinates | |
122 | 133 | fn game_coords(&self) -> Coord { |
123 | 134 | self.loc.to_discrete(TILE_SIZE as f32) |
124 | 135 | } |
125 | 136 | } |
126 | 137 | |
138 | /// A `Delta` is the amount of calculated movement found for a given | |
139 | /// entity when it attempts to move. | |
127 | 140 | #[derive(Debug)] |
128 | 141 | struct Delta { |
129 | 142 | dx: f32, |
149 | 162 | } |
150 | 163 | |
151 | 164 | impl<T> Grid<T> { |
152 |
pub fn new_with<F |
|
165 | pub fn new_with<F>( | |
166 | width: u16, | |
167 | height: u16, | |
168 | elem: F, | |
169 | ) -> Grid<T> | |
170 | where F: Fn(u16, u16) -> T | |
171 | { | |
153 | 172 | let mut elems = Vec::with_capacity((width * height) as usize); |
154 | 173 | for y in 0..height { |
155 | 174 | for x in 0..width { |
210 | 229 | &self.entity[c] |
211 | 230 | } |
212 | 231 | |
232 | /// Take a Tiled-format map and ingest it into our internal map | |
233 | /// format. (Might be a good idea eventually to use a custom | |
234 | /// format, but Tiled is great for now.) | |
213 | 235 | pub fn from_tiled(map: &tiled::Map) -> Board { |
214 | 236 | fn offset_from_gid(n: u32) -> Option<Coord> { |
215 | 237 | if n < 1 || n > 1024 { |
237 | 259 | }); |
238 | 260 | Board { base, entity } |
239 | 261 | } |
240 | } | |
262 | ||
263 | pub fn each_tile<F>(&self, mut f: F) | |
264 | where F: FnMut(usize, usize, &Tile) | |
265 | { | |
266 | for x in 0..self.base.width { | |
267 | for y in 0..self.base.height { | |
268 | f(x as usize, y as usize, &self.base[Pair::new(x, y)]); | |
269 | } | |
270 | } | |
271 | } | |
272 | } |
229 | 229 | }) |
230 | 230 | } |
231 | 231 | |
232 | pub fn set_texture(&self, s: &str, t: &Texture) -> Result<(), Error>{ | |
233 | unsafe { | |
234 | gl::ActiveTexture(gl::TEXTURE0); | |
235 | gl::BindTexture(gl::TEXTURE_2D, t.idx); | |
232 | pub fn set_texture( | |
233 | &self, | |
234 | s: &str, | |
235 | tex: &Texture, | |
236 | n: i32, | |
237 | ) -> Result<(), Error>{ | |
238 | unsafe { | |
239 | gl::ActiveTexture(match n { | |
240 | 0 => gl::TEXTURE0, | |
241 | 1 => gl::TEXTURE1, | |
242 | 2 => gl::TEXTURE2, | |
243 | _ => panic!("too many textures, i guess"), | |
244 | }); | |
245 | gl::BindTexture(gl::TEXTURE_2D, tex.idx); | |
236 | 246 | let t = gl::GetUniformLocation( |
237 | 247 | self.p, |
238 | 248 | ffi::CString::new(s)?.as_ptr(), |
239 | 249 | ); |
240 |
gl::Uniform1i(t, |
|
250 | gl::Uniform1i(t, n); | |
241 | 251 | } |
242 | 252 | Ok(()) |
243 | 253 | } |
376 | 386 | pub fn draw(&self) { |
377 | 387 | self.bind(); |
378 | 388 | unsafe { |
379 |
gl::DrawArrays(gl::TRIANGLE |
|
389 | gl::DrawArrays(gl::TRIANGLES, 0, self.len as i32); | |
380 | 390 | } |
381 | 391 | self.unbind(); |
382 | 392 | } |
1 | 1 | #![allow(dead_code)] |
2 | 2 | use gl; |
3 | 3 | use std::mem; |
4 | ||
5 | use board; | |
4 | 6 | |
5 | 7 | /// A trait defined on each type used to create a VBO |
6 | 8 | pub trait Vertex { |
10 | 12 | fn normal_location() -> Option<(i32, i32)>; |
11 | 13 | } |
12 | 14 | |
15 | #[derive(Debug, PartialEq)] | |
13 | 16 | pub struct V2D { |
14 | 17 | pub x: gl::GLfloat, |
15 | 18 | pub y: gl::GLfloat, |
84 | 87 | None |
85 | 88 | } |
86 | 89 | } |
90 | ||
91 | pub fn make_grid(w: usize, h: usize) -> Vec<V2D> { | |
92 | let mut vec = Vec::with_capacity(w * h * 4); | |
93 | let x_stride = 2.0 / w as f32; | |
94 | let y_stride = 2.0 / h as f32; | |
95 | for x in 0..w { | |
96 | for y in 0..h { | |
97 | let x = x as f32; | |
98 | let y = y as f32; | |
99 | let o = 1.0 / 32.0; | |
100 | vec.extend(vec![ | |
101 | V2D { x: x_stride * (x + 1.0) - 1.0, y: y_stride * y - 1.0, u: o , v: o }, | |
102 | V2D { x: x_stride * x - 1.0, y: y_stride * y - 1.0, u: 0.0, v: o }, | |
103 | V2D { x: x_stride * (x + 1.0) - 1.0, y: y_stride * (y + 1.0) - 1.0, u: o, v: 0.0 }, | |
104 | V2D { x: x_stride * x - 1.0, y: y_stride * (y + 1.0) - 1.0, u: 0.0, v: 0.0 }, | |
105 | ]); | |
106 | } | |
107 | } | |
108 | vec | |
109 | } | |
110 | ||
111 | ||
112 | pub fn make_grid_with(w: usize, h: usize, b: &board::Board) -> Vec<V2D> { | |
113 | let mut vec = Vec::with_capacity(w * h * 4); | |
114 | let x_stride = 2.0 / w as f32; | |
115 | let y_stride = 2.0 / h as f32; | |
116 | let o_stride = 1.0 / 32.0; | |
117 | b.each_tile(|x, y, t| { | |
118 | let x = x as f32; | |
119 | let y = h as f32 - y as f32 - 1.0; | |
120 | let tx = (t.sprite.x as f32) * o_stride; | |
121 | let ty = (t.sprite.y as f32) * o_stride; | |
122 | vec.extend(vec![ | |
123 | V2D { | |
124 | x: x_stride * (x + 1.0) - 1.0, | |
125 | y: y_stride * y - 1.0, | |
126 | u: tx + o_stride, | |
127 | v: ty + o_stride, | |
128 | }, | |
129 | V2D { | |
130 | x: x_stride * x - 1.0, | |
131 | y: y_stride * y - 1.0, | |
132 | u: tx, | |
133 | v: ty + o_stride, | |
134 | }, | |
135 | V2D { | |
136 | x: x_stride * (x + 1.0) - 1.0, | |
137 | y: y_stride * (y + 1.0) - 1.0, | |
138 | u: tx + o_stride, | |
139 | v: ty, | |
140 | }, | |
141 | ||
142 | V2D { | |
143 | x: x_stride * x - 1.0, | |
144 | y: y_stride * y - 1.0, | |
145 | u: tx, | |
146 | v: ty + o_stride, | |
147 | }, | |
148 | V2D { | |
149 | x: x_stride * (x + 1.0) - 1.0, | |
150 | y: y_stride * (y + 1.0) - 1.0, | |
151 | u: tx + o_stride, | |
152 | v: ty, | |
153 | }, | |
154 | V2D { | |
155 | x: x_stride * x - 1.0, | |
156 | y: y_stride * (y + 1.0) - 1.0, | |
157 | u: tx, | |
158 | v: ty, | |
159 | }, | |
160 | ]); | |
161 | }); | |
162 | vec | |
163 | } |
13 | 13 | // pub mod audio; |
14 | 14 | |
15 | 15 | use graphics as gfx; |
16 | use graphics::vertices::V2D; | |
17 | 16 | |
18 | static TILE_DATA: [V2D; 4] = [ | |
19 | V2D { x: 0.5, y: -0.5, u: 1.0, v: 1.0 }, | |
20 | V2D { x: -0.5, y: -0.5, u: 0.0, v: 1.0 }, | |
21 | V2D { x: 0.5, y: 0.5, u: 1.0, v: 0.0 }, | |
22 | V2D { x: -0.5, y: 0.5, u: 0.0, v: 0.0 }, | |
23 | ]; | |
17 | // static TILE_DATA: [V2D; 4] = [ | |
18 | // V2D { x: 0.5, y: -0.5, u: 1.0, v: 1.0 }, | |
19 | // V2D { x: -0.5, y: -0.5, u: 0.0, v: 1.0 }, | |
20 | // V2D { x: 0.5, y: 0.5, u: 1.0, v: 0.0 }, | |
21 | // V2D { x: -0.5, y: 0.5, u: 0.0, v: 0.0 }, | |
22 | // ]; | |
24 | 23 | |
25 | 24 | // Shader sources |
26 | 25 | static VS_SRC: &'static str = include_str!("../shaders/basic_vertex.glsl"); |
31 | 30 | /// event loop |
32 | 31 | pub fn main_loop() -> Result<(), gfx::Error> { |
33 | 32 | let t = tiled::parse_file( |
34 |
std::path::Path::new("/home/gdritter/projects/animaltransiro/areas/ |
|
33 | std::path::Path::new("/home/gdritter/projects/animaltransiro/areas/west.tmx") | |
35 | 34 | ).unwrap(); |
36 | 35 | let board = board::Board::from_tiled(&t); |
37 | 36 | |
38 | 37 | println!("{:#?}", board); |
39 | 38 | |
40 | return Ok(()); | |
41 | 39 | // let audio = audio::Audio::init()?; |
42 | 40 | let window = gfx::Window::create()?; |
43 | 41 | |
46 | 44 | gfx::Shader::compile(gfx::ShaderType::Fragment, FS_SRC)?, |
47 | 45 | ])?; |
48 | 46 | |
49 |
let tex = gfx::Texture::new_from_png(" |
|
47 | let tex = gfx::Texture::new_from_png("/home/gdritter/projects/animaltransiro/tiles/spritesheet.png")?; | |
48 | let nrm = gfx::Texture::new_from_png("/home/gdritter/projects/animaltransiro/tiles/spritesheet-normal.png")?; | |
50 | 49 | |
50 | let tile_data = graphics::vertices::make_grid_with( | |
51 | board::BOARD_WIDTH as usize, | |
52 | board::BOARD_HEIGHT as usize, | |
53 | &board, | |
54 | ); | |
51 | 55 | let vbo = gfx::VertexBuffer::new_array_buffer( |
52 | 56 | gfx::VertexArray::new(&program), |
53 |
& |
|
57 | &tile_data, | |
54 | 58 | ); |
55 | 59 | |
56 | 60 | program.use_program(); |
59 | 63 | vbo.bind_position("position")?; |
60 | 64 | vbo.bind_uv("uv")?; |
61 | 65 | vbo.unbind(); |
66 | ||
67 | program.set_texture("tex", &tex, 0).unwrap(); | |
68 | program.set_texture("nrm", &nrm, 1).unwrap(); | |
62 | 69 | |
63 | 70 | window.run(|event| { |
64 | 71 | use glutin::{ControlFlow, Event, WindowEvent, VirtualKeyCode}; |
85 | 92 | } |
86 | 93 | |
87 | 94 | gfx::clear(); |
88 | program.set_texture("tex", &tex).unwrap(); | |
89 | 95 | vbo.draw(); |
90 | 96 | |
91 | 97 | ControlFlow::Continue |