rust/lib-hedgewars-engine/src/render/map.rs
changeset 14714 4df1aac5f090
parent 14705 19122a329774
child 14718 5915a199cb81
equal deleted inserted replaced
14711:40809bfd44af 14714:4df1aac5f090
     1 use integral_geometry::{Point, Rect, Size};
     1 use integral_geometry::{GridIndex, 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     Buffer, InputElement, InputFormat, InputLayout, Shader, Texture2D, VariableBinding,
     6     Buffer, InputElement, InputFormat, InputLayout, Shader, Texture2D, VariableBinding,
    73     tile_draw_calls: Vec<DrawTile>,
    73     tile_draw_calls: Vec<DrawTile>,
    74     index_offset: u16,
    74     index_offset: u16,
    75     tile_shader: Shader,
    75     tile_shader: Shader,
    76     tile_layout: InputLayout,
    76     tile_layout: InputLayout,
    77 
    77 
    78     tile_width: u32,
    78     tile_size: Size,
    79     tile_height: u32,
    79     num_tile_x: usize,
    80     num_tile_x: i32,
       
    81 }
    80 }
    82 
    81 
    83 impl MapRenderer {
    82 impl MapRenderer {
    84     pub fn new(tile_width: u32, tile_height: u32) -> Self {
    83     pub fn new(tile_size: Size) -> Self {
       
    84         debug_assert!(tile_size.is_power_of_two());
       
    85 
    85         let tile_shader = Shader::new(
    86         let tile_shader = Shader::new(
    86             VERTEX_SHADER,
    87             VERTEX_SHADER,
    87             Some(PIXEL_SHADER),
    88             Some(PIXEL_SHADER),
    88             &[
    89             &[
    89                 VariableBinding::Attribute("Position", 0),
    90                 VariableBinding::Attribute("Position", 0),
    91                 VariableBinding::Sampler("Texture", 0),
    92                 VariableBinding::Sampler("Texture", 0),
    92             ],
    93             ],
    93         )
    94         )
    94         .unwrap();
    95         .unwrap();
    95 
    96 
       
    97         let vertex_size = std::mem::size_of::<TileVertex>() as u32;
    96         let tile_layout = InputLayout::new(vec![
    98         let tile_layout = InputLayout::new(vec![
    97             // position
    99             // position
    98             InputElement {
   100             InputElement {
    99                 shader_slot: 0,
   101                 shader_slot: 0,
   100                 buffer_slot: 0,
   102                 buffer_slot: 0,
   101                 format: InputFormat::Float(gl::FLOAT, false),
   103                 format: InputFormat::Float(gl::FLOAT, false),
   102                 components: 2,
   104                 components: 2,
   103                 stride: 20,
   105                 stride: vertex_size,
   104                 offset: 0,
   106                 offset: 0,
   105             },
   107             },
   106             // uv
   108             // uv
   107             InputElement {
   109             InputElement {
   108                 shader_slot: 1,
   110                 shader_slot: 1,
   109                 buffer_slot: 0,
   111                 buffer_slot: 0,
   110                 format: InputFormat::Float(gl::FLOAT, false),
   112                 format: InputFormat::Float(gl::FLOAT, false),
   111                 components: 3,
   113                 components: 3,
   112                 stride: 20,
   114                 stride: vertex_size,
   113                 offset: 8,
   115                 offset: 8,
   114             },
   116             },
   115         ]);
   117         ]);
   116 
   118 
   117         MapRenderer {
   119         MapRenderer {
   126 
   128 
   127             tile_draw_calls: Vec::new(),
   129             tile_draw_calls: Vec::new(),
   128             tile_shader,
   130             tile_shader,
   129             tile_layout,
   131             tile_layout,
   130 
   132 
   131             tile_width,
   133             tile_size,
   132             tile_height,
       
   133             num_tile_x: 0,
   134             num_tile_x: 0,
   134         }
   135         }
   135     }
   136     }
   136 
   137 
   137     pub fn init(&mut self, land: &Vec2D<u32>) {
   138     pub fn init(&mut self, land: &Vec2D<u32>) {
   138         // clear tiles, but keep our textures for potential re-use
   139         // clear tiles, but keep our textures for potential re-use
   139         self.tiles.clear();
   140         self.tiles.clear();
   140 
   141 
   141         let tw = self.tile_width as usize;
   142         let tw = self.tile_size.width;
   142         let th = self.tile_height as usize;
   143         let th = self.tile_size.height;
   143         let lw = land.width();
   144         let lw = land.width();
   144         let lh = land.height();
   145         let lh = land.height();
   145         let num_tile_x = lw / tw + if lw % tw != 0 { 1 } else { 0 };
   146         let num_tile_x = lw / tw;
   146         let num_tile_y = lh / th + if lh % th != 0 { 1 } else { 0 };
   147         let num_tile_y = lh / th;
   147 
   148 
   148         self.num_tile_x = num_tile_x as i32;
   149         self.num_tile_x = num_tile_x;
   149 
   150 
   150         for y in 0..num_tile_y {
   151         for y in 0..num_tile_y {
   151             for x in 0..num_tile_x {
   152             for x in 0..num_tile_x {
   152                 let idx = x + y * num_tile_x;
   153                 let idx = x + y * num_tile_x;
   153 
   154 
   164 
   165 
   165                 let texture_index = if idx >= self.textures.len() {
   166                 let texture_index = if idx >= self.textures.len() {
   166                     let texture = Texture2D::with_data(
   167                     let texture = Texture2D::with_data(
   167                         data,
   168                         data,
   168                         stride,
   169                         stride,
   169                         self.tile_width,
   170                         self.tile_size.width as u32,
   170                         self.tile_height,
   171                         self.tile_size.height as u32,
   171                         gl::RGBA8,
   172                         gl::RGBA8,
   172                         gl::RGBA,
   173                         gl::RGBA,
   173                         gl::UNSIGNED_BYTE,
   174                         gl::UNSIGNED_BYTE,
   174                         gl::NEAREST,
   175                         gl::NEAREST,
   175                     );
   176                     );
   177                     let texture_index = self.textures.len();
   178                     let texture_index = self.textures.len();
   178                     self.textures.push(texture);
   179                     self.textures.push(texture);
   179 
   180 
   180                     texture_index
   181                     texture_index
   181                 } else {
   182                 } else {
   182                     let texture_region = Rect::new(
   183                     let texture_region = Rect::at_origin(self.tile_size);
   183                         Point::new(0, 0),
       
   184                         Point::new(self.tile_width as i32, self.tile_height as i32),
       
   185                     );
       
   186 
   184 
   187                     self.textures[idx].update(
   185                     self.textures[idx].update(
   188                         texture_region,
   186                         texture_region,
   189                         data,
   187                         data,
   190                         stride,
   188                         stride,
   196 
   194 
   197                 let tile = MapTile {
   195                 let tile = MapTile {
   198                     texture_index: texture_index as u32,
   196                     texture_index: texture_index as u32,
   199 
   197 
   200                     // TODO: are there ever non-power of two textures?
   198                     // TODO: are there ever non-power of two textures?
   201                     width: self.tile_width,
   199                     width: self.tile_size.width as u32,
   202                     height: self.tile_height,
   200                     height: self.tile_size.height as u32,
   203                 };
   201                 };
   204                 self.tiles.push(tile);
   202                 self.tiles.push(tile);
   205             }
   203             }
   206         }
   204         }
   207     }
   205     }
   213         self.tile_indices.clear();
   211         self.tile_indices.clear();
   214         self.tile_draw_calls.clear();
   212         self.tile_draw_calls.clear();
   215         self.index_offset = 0;
   213         self.index_offset = 0;
   216 
   214 
   217         for (idx, tile) in self.tiles.iter().enumerate() {
   215         for (idx, tile) in self.tiles.iter().enumerate() {
   218             let tile_x = idx as i32 % self.num_tile_x;
   216             let tile_x = idx % self.num_tile_x;
   219             let tile_y = idx as i32 / self.num_tile_x;
   217             let tile_y = idx / self.num_tile_x;
   220             let tile_w = self.tile_width as i32;
   218             let tile_w = self.tile_size.width;
   221             let tile_h = self.tile_height as i32;
   219             let tile_h = self.tile_size.width;
   222 
   220 
   223             let origin = Point::new(tile_x * tile_w, tile_y * tile_h);
   221             let origin = Point::new((tile_x * tile_w) as i32, (tile_y * tile_h) as i32);
   224             let tile_rect = Rect::new(origin, origin + Point::new(tile_w, tile_h));
   222             let tile_rect = Rect::from_size(origin, self.tile_size);
   225 
   223 
   226             if viewport.intersects(&tile_rect) {
   224             if viewport.intersects(&tile_rect) {
   227                 // lazy
   225                 // lazy
   228                 //dbg!(origin);
   226                 //dbg!(origin);
   229                 let tile_x = origin.x as f32;
   227                 let tile_x = origin.x as f32;
   272             Some(&self.tile_index_buffer),
   270             Some(&self.tile_index_buffer),
   273         );
   271         );
   274 
   272 
   275         let ortho = {
   273         let ortho = {
   276             let l = viewport.left() as f32;
   274             let l = viewport.left() as f32;
   277             let r = viewport.right() as f32;
   275             let w = viewport.width() as f32;
   278             let b = viewport.bottom() as f32;
   276             let h = viewport.height() as f32;
   279             let t = viewport.top() as f32;
   277             let t = viewport.top() as f32;
   280 
   278 
   281             [
   279             [
   282                 2f32 / (r - l),
   280                 2f32 / w,
   283                 0f32,
   281                 0f32,
   284                 0f32,
   282                 0f32,
   285                 0f32,
   283                 0f32,
   286                 0f32,
   284                 0f32,
   287                 2f32 / (t - b),
   285                 2f32 / -h,
   288                 0f32,
   286                 0f32,
   289                 0f32,
   287                 0f32,
   290                 0f32,
   288                 0f32,
   291                 0f32,
   289                 0f32,
   292                 0.5f32,
   290                 0.5f32,
   293                 0f32,
   291                 0f32,
   294                 (r + l) / (l - r),
   292                 -(2.0 * l + w) / w,
   295                 (t + b) / (b - t),
   293                 (2.0 * t + h) / h,
   296                 0.5f32,
   294                 0.5f32,
   297                 1f32,
   295                 1f32,
   298             ]
   296             ]
   299         };
   297         };
   300 
   298