Start using normal map in drawing as well
Getty Ritter
7 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 |