rust/lib-hedgewars-engine/src/render/map.rs
changeset 14726 19122a329774
parent 14723 29dbe9ce8b7d
child 14735 4df1aac5f090
equal deleted inserted replaced
14725:12db7e435ea6 14726:19122a329774
     1 use integral_geometry::{Point, Rect, Size};
     1 use integral_geometry::{Point, Rect, Size};
     2 use land2d::{Land2D};
     2 use land2d::Land2D;
     3 use vec2d::{Vec2D};
     3 use vec2d::Vec2D;
     4 
     4 
     5 use super::gl::{
     5 use super::gl::{
     6     Texture2D,
     6     Buffer, InputElement, InputFormat, InputLayout, Shader, Texture2D, VariableBinding,
     7     Buffer,
       
     8     Shader,
       
     9     InputLayout,
       
    10     VariableBinding,
       
    11     InputElement,
       
    12     InputFormat,
       
    13 };
     7 };
    14 
     8 
    15 // TODO: temp
     9 // TODO: temp
    16 const VERTEX_SHADER: &'static str = r#"
    10 const VERTEX_SHADER: &'static str = r#"
    17 #version 150
    11 #version 150
    78     tile_indices: Vec<u16>,
    72     tile_indices: Vec<u16>,
    79     tile_draw_calls: Vec<DrawTile>,
    73     tile_draw_calls: Vec<DrawTile>,
    80     index_offset: u16,
    74     index_offset: u16,
    81     tile_shader: Shader,
    75     tile_shader: Shader,
    82     tile_layout: InputLayout,
    76     tile_layout: InputLayout,
    83     
    77 
    84     tile_width: u32,
    78     tile_width: u32,
    85     tile_height: u32,
    79     tile_height: u32,
    86     num_tile_x: i32,
    80     num_tile_x: i32,
    87 }
    81 }
    88 
    82 
    93             Some(PIXEL_SHADER),
    87             Some(PIXEL_SHADER),
    94             &[
    88             &[
    95                 VariableBinding::Attribute("Position", 0),
    89                 VariableBinding::Attribute("Position", 0),
    96                 VariableBinding::Attribute("Uv", 1),
    90                 VariableBinding::Attribute("Uv", 1),
    97                 VariableBinding::Sampler("Texture", 0),
    91                 VariableBinding::Sampler("Texture", 0),
    98             ]
    92             ],
    99         ).unwrap();
    93         )
       
    94         .unwrap();
   100 
    95 
   101         let tile_layout = InputLayout::new(vec![
    96         let tile_layout = InputLayout::new(vec![
   102             // position
    97             // position
   103             InputElement {
    98             InputElement {
   104                 shader_slot: 0,
    99                 shader_slot: 0,
   105                 buffer_slot: 0,
   100                 buffer_slot: 0,
   106                 format: InputFormat::Float(gl::FLOAT, false),
   101                 format: InputFormat::Float(gl::FLOAT, false),
   107                 components: 2,
   102                 components: 2,
   108                 stride: 20,
   103                 stride: 20,
   109                 offset: 0
   104                 offset: 0,
   110             },
   105             },
   111             // uv
   106             // uv
   112             InputElement {
   107             InputElement {
   113                 shader_slot: 1,
   108                 shader_slot: 1,
   114                 buffer_slot: 0,
   109                 buffer_slot: 0,
   115                 format: InputFormat::Float(gl::FLOAT, false),
   110                 format: InputFormat::Float(gl::FLOAT, false),
   116                 components: 3,
   111                 components: 3,
   117                 stride: 20,
   112                 stride: 20,
   118                 offset: 8
   113                 offset: 8,
   119             },
   114             },
   120         ]);
   115         ]);
   121         
   116 
   122         MapRenderer {
   117         MapRenderer {
   123             tiles: Vec::new(),
   118             tiles: Vec::new(),
   124             textures: Vec::new(),
   119             textures: Vec::new(),
   125             
   120 
   126             tile_vertex_buffer: Buffer::empty(gl::ARRAY_BUFFER, gl::DYNAMIC_DRAW),
   121             tile_vertex_buffer: Buffer::empty(gl::ARRAY_BUFFER, gl::DYNAMIC_DRAW),
   127             tile_index_buffer: Buffer::empty(gl::ELEMENT_ARRAY_BUFFER, gl::DYNAMIC_DRAW),
   122             tile_index_buffer: Buffer::empty(gl::ELEMENT_ARRAY_BUFFER, gl::DYNAMIC_DRAW),
   128             tile_vertices: Vec::new(),
   123             tile_vertices: Vec::new(),
   129             tile_indices: Vec::new(),
   124             tile_indices: Vec::new(),
   130             index_offset: 0,
   125             index_offset: 0,
   164                     let data = unsafe { &land.as_bytes()[offset..] };
   159                     let data = unsafe { &land.as_bytes()[offset..] };
   165                     let stride = land.width();
   160                     let stride = land.width();
   166 
   161 
   167                     (data, stride as u32)
   162                     (data, stride as u32)
   168                 };
   163                 };
   169                 
   164 
   170                 let texture_index = if idx >= self.textures.len() {
   165                 let texture_index = if idx >= self.textures.len() {
   171                     let texture = Texture2D::with_data(
   166                     let texture = Texture2D::with_data(
   172                         data,
   167                         data,
   173                         stride,
   168                         stride,
   174                         self.tile_width,
   169                         self.tile_width,
   175                         self.tile_height,
   170                         self.tile_height,
   176                         gl::RGBA8,
   171                         gl::RGBA8,
   177                         gl::RGBA,
   172                         gl::RGBA,
   178                         gl::UNSIGNED_BYTE,
   173                         gl::UNSIGNED_BYTE,
   179                         gl::NEAREST
   174                         gl::NEAREST,
   180                     );
   175                     );
   181 
   176 
   182                     let texture_index = self.textures.len();
   177                     let texture_index = self.textures.len();
   183                     self.textures.push(texture);
   178                     self.textures.push(texture);
   184 
   179 
   185                     texture_index
   180                     texture_index
   186                 } else {
   181                 } else {
   187                     let texture_region = Rect::new(
   182                     let texture_region = Rect::new(
   188                         Point::new(0, 0),
   183                         Point::new(0, 0),
   189                         Point::new(self.tile_width as i32, self.tile_height as i32)
   184                         Point::new(self.tile_width as i32, self.tile_height as i32),
   190                     );
   185                     );
   191 
   186 
   192                     self.textures[idx].update(texture_region, data, stride, gl::RGBA, gl::UNSIGNED_BYTE);
   187                     self.textures[idx].update(
       
   188                         texture_region,
       
   189                         data,
       
   190                         stride,
       
   191                         gl::RGBA,
       
   192                         gl::UNSIGNED_BYTE,
       
   193                     );
   193                     idx
   194                     idx
   194                 };
   195                 };
   195 
   196 
   196                 let tile = MapTile {
   197                 let tile = MapTile {
   197                     texture_index: texture_index as u32,
   198                     texture_index: texture_index as u32,
   198                     
   199 
   199                     // TODO: are there ever non-power of two textures?
   200                     // TODO: are there ever non-power of two textures?
   200                     width: self.tile_width,
   201                     width: self.tile_width,
   201                     height: self.tile_height,
   202                     height: self.tile_height,
   202                 };
   203                 };
   203                 self.tiles.push(tile);
   204                 self.tiles.push(tile);
   204             }
   205             }
   205         }
   206         }
   206     }
   207     }
   207 
   208 
   208     pub fn update(&mut self, land: &Land2D<u32>, region: Rect) {
   209     pub fn update(&mut self, land: &Land2D<u32>, region: Rect) {}
   209 
       
   210     }
       
   211 
   210 
   212     pub fn render(&mut self, viewport: Rect) {
   211     pub fn render(&mut self, viewport: Rect) {
   213         self.tile_vertices.clear();
   212         self.tile_vertices.clear();
   214         self.tile_indices.clear();
   213         self.tile_indices.clear();
   215         self.tile_draw_calls.clear();
   214         self.tile_draw_calls.clear();
   216         self.index_offset = 0;
   215         self.index_offset = 0;
   217         
   216 
   218         for (idx, tile) in self.tiles.iter().enumerate() {
   217         for (idx, tile) in self.tiles.iter().enumerate() {
   219             let tile_x = idx as i32 % self.num_tile_x;
   218             let tile_x = idx as i32 % self.num_tile_x;
   220             let tile_y = idx as i32 / self.num_tile_x;
   219             let tile_y = idx as i32 / self.num_tile_x;
   221             let tile_w = self.tile_width as i32;
   220             let tile_w = self.tile_width as i32;
   222             let tile_h = self.tile_height as i32;
   221             let tile_h = self.tile_height as i32;
   232                 let tile_w = tile_x + tile_w as f32;
   231                 let tile_w = tile_x + tile_w as f32;
   233                 let tile_h = tile_y + tile_h as f32;
   232                 let tile_h = tile_y + tile_h as f32;
   234                 let uv_depth = tile.texture_index as f32;
   233                 let uv_depth = tile.texture_index as f32;
   235 
   234 
   236                 //dbg!(tile_x);
   235                 //dbg!(tile_x);
   237                 let tl = TileVertex { pos: [tile_x, tile_y], uv: [0f32, 0f32, uv_depth] };
   236                 let tl = TileVertex {
   238                 let bl = TileVertex { pos: [tile_x, tile_h], uv: [0f32, 1f32, uv_depth] };
   237                     pos: [tile_x, tile_y],
   239                 let br = TileVertex { pos: [tile_w, tile_h], uv: [1f32, 1f32, uv_depth] };
   238                     uv: [0f32, 0f32, uv_depth],
   240                 let tr = TileVertex { pos: [tile_w, tile_y], uv: [1f32, 0f32, uv_depth] };
   239                 };
       
   240                 let bl = TileVertex {
       
   241                     pos: [tile_x, tile_h],
       
   242                     uv: [0f32, 1f32, uv_depth],
       
   243                 };
       
   244                 let br = TileVertex {
       
   245                     pos: [tile_w, tile_h],
       
   246                     uv: [1f32, 1f32, uv_depth],
       
   247                 };
       
   248                 let tr = TileVertex {
       
   249                     pos: [tile_w, tile_y],
       
   250                     uv: [1f32, 0f32, uv_depth],
       
   251                 };
   241 
   252 
   242                 self.tile_vertices.extend(&[tl, bl, br, tr]);
   253                 self.tile_vertices.extend(&[tl, bl, br, tr]);
   243 
   254 
   244                 let i = self.index_offset;
   255                 let i = self.index_offset;
   245                 self.tile_indices.extend(&[
   256                 self.tile_indices
   246                     i + 0, i + 1, i + 2,
   257                     .extend(&[i + 0, i + 1, i + 2, i + 2, i + 3, i + 0]);
   247                     i + 2, i + 3, i + 0,
       
   248                 ]);
       
   249                 self.index_offset += 4;
   258                 self.index_offset += 4;
   250 
   259 
   251                 self.tile_draw_calls.push(DrawTile {
   260                 self.tile_draw_calls.push(DrawTile {
   252                     texture_index: tile.texture_index,
   261                     texture_index: tile.texture_index,
   253                     index_len: 6
   262                     index_len: 6,
   254                 });
   263                 });
   255             }
   264             }
   256         }
   265         }
   257 
   266 
   258         self.tile_vertex_buffer.write_typed(&self.tile_vertices);
   267         self.tile_vertex_buffer.write_typed(&self.tile_vertices);
   259         self.tile_index_buffer.write_typed(&self.tile_indices);
   268         self.tile_index_buffer.write_typed(&self.tile_indices);
   260 
   269 
   261         let _g = self.tile_layout.bind(&[
   270         let _g = self.tile_layout.bind(
   262             (0, &self.tile_vertex_buffer)
   271             &[(0, &self.tile_vertex_buffer)],
   263         ], Some(&self.tile_index_buffer));
   272             Some(&self.tile_index_buffer),
       
   273         );
   264 
   274 
   265         let ortho = {
   275         let ortho = {
   266             let l = viewport.left() as f32;
   276             let l = viewport.left() as f32;
   267             let r = viewport.right() as f32;
   277             let r = viewport.right() as f32;
   268             let b = viewport.bottom() as f32;
   278             let b = viewport.bottom() as f32;
   269             let t = viewport.top() as f32;
   279             let t = viewport.top() as f32;
   270 
   280 
   271             [
   281             [
   272                 2f32 / (r - l),    0f32,              0f32,   0f32,
   282                 2f32 / (r - l),
   273                 0f32,              2f32 / (t - b),    0f32,   0f32,
   283                 0f32,
   274                 0f32,              0f32,              0.5f32, 0f32,
   284                 0f32,
   275                 (r + l) / (l - r), (t + b) / (b - t), 0.5f32, 1f32,
   285                 0f32,
       
   286                 0f32,
       
   287                 2f32 / (t - b),
       
   288                 0f32,
       
   289                 0f32,
       
   290                 0f32,
       
   291                 0f32,
       
   292                 0.5f32,
       
   293                 0f32,
       
   294                 (r + l) / (l - r),
       
   295                 (t + b) / (b - t),
       
   296                 0.5f32,
       
   297                 1f32,
   276             ]
   298             ]
   277         };
   299         };
   278 
   300 
   279         self.tile_shader.bind();
   301         self.tile_shader.bind();
   280         self.tile_shader.set_matrix("Projection", ortho.as_ptr());
   302         self.tile_shader.set_matrix("Projection", ortho.as_ptr());
   281         
   303 
   282         let mut draw_offset = 0;
   304         let mut draw_offset = 0;
   283         for draw_call in &self.tile_draw_calls {
   305         for draw_call in &self.tile_draw_calls {
   284             unsafe {
   306             unsafe {
   285                 self.tile_shader.bind_texture_2d(0, &self.textures[draw_call.texture_index as usize]);
   307                 self.tile_shader
   286                 
   308                     .bind_texture_2d(0, &self.textures[draw_call.texture_index as usize]);
       
   309 
   287                 gl::DrawElements(
   310                 gl::DrawElements(
   288                     gl::TRIANGLES,
   311                     gl::TRIANGLES,
   289                     draw_call.index_len as i32,
   312                     draw_call.index_len as i32,
   290                     gl::UNSIGNED_SHORT,
   313                     gl::UNSIGNED_SHORT,
   291                     draw_offset as *const _
   314                     draw_offset as *const _,
   292                 );
   315                 );
   293             }
   316             }
   294 
   317 
   295             draw_offset += draw_call.index_len * 2;
   318             draw_offset += draw_call.index_len * 2;
   296         }
   319         }
   297     }
   320     }
   298 }
   321 }
   299 
       
   300